4 * Copyright (C) International Business Machines Corp., 2002,2010
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/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <asm/uaccess.h>
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
47 #ifdef CONFIG_CIFS_POSIX
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53 {LANMAN_PROT, "\2LM1.2X002"},
54 {LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56 {CIFS_PROT, "\2NT LM 0.12"},
57 {POSIX_PROT, "\2POSIX 2"},
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66 {LANMAN_PROT, "\2LM1.2X002"},
67 {LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69 {CIFS_PROT, "\2NT LM 0.12"},
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
90 * Mark as invalid, all open files on tree connections since they
91 * were closed when session to server was lost.
94 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
96 struct cifsFileInfo *open_file = NULL;
97 struct list_head *tmp;
98 struct list_head *tmp1;
100 /* list all files open on tree connection and mark them invalid */
101 spin_lock(&cifs_file_list_lock);
102 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
103 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
104 open_file->invalidHandle = true;
105 open_file->oplock_break_cancelled = true;
107 spin_unlock(&cifs_file_list_lock);
109 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
114 /* reconnect the socket, tcon, and smb session if needed */
116 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
119 struct cifs_ses *ses;
120 struct TCP_Server_Info *server;
121 struct nls_table *nls_codepage;
124 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
125 * tcp and smb session status done differently for those three - in the
132 server = ses->server;
135 * only tree disconnect, open, and write, (and ulogoff which does not
136 * have tcon) are allowed as we start force umount
138 if (tcon->tidStatus == CifsExiting) {
139 if (smb_command != SMB_COM_WRITE_ANDX &&
140 smb_command != SMB_COM_OPEN_ANDX &&
141 smb_command != SMB_COM_TREE_DISCONNECT) {
142 cFYI(1, "can not send cmd %d while umounting",
149 * Give demultiplex thread up to 10 seconds to reconnect, should be
150 * greater than cifs socket timeout which is 7 seconds
152 while (server->tcpStatus == CifsNeedReconnect) {
153 wait_event_interruptible_timeout(server->response_q,
154 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
156 /* are we still trying to reconnect? */
157 if (server->tcpStatus != CifsNeedReconnect)
161 * on "soft" mounts we wait once. Hard mounts keep
162 * retrying until process is killed or server comes
166 cFYI(1, "gave up waiting on reconnect in smb_init");
171 if (!ses->need_reconnect && !tcon->need_reconnect)
174 nls_codepage = load_nls_default();
177 * need to prevent multiple threads trying to simultaneously
178 * reconnect the same SMB session
180 mutex_lock(&ses->session_mutex);
181 rc = cifs_negotiate_protocol(0, ses);
182 if (rc == 0 && ses->need_reconnect)
183 rc = cifs_setup_session(0, ses, nls_codepage);
185 /* do we need to reconnect tcon? */
186 if (rc || !tcon->need_reconnect) {
187 mutex_unlock(&ses->session_mutex);
191 cifs_mark_open_files_invalid(tcon);
192 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
193 mutex_unlock(&ses->session_mutex);
194 cFYI(1, "reconnect tcon rc = %d", rc);
200 * FIXME: check if wsize needs updated due to negotiated smb buffer
203 atomic_inc(&tconInfoReconnectCount);
205 /* tell server Unix caps we support */
206 if (ses->capabilities & CAP_UNIX)
207 reset_cifs_unix_caps(0, tcon, NULL, NULL);
210 * Removed call to reopen open files here. It is safer (and faster) to
211 * reopen files one at a time as needed in read and write.
213 * FIXME: what about file locks? don't we need to reclaim them ASAP?
218 * Check if handle based operation so we know whether we can continue
219 * or not without returning to caller to reset file handle
221 switch (smb_command) {
222 case SMB_COM_READ_ANDX:
223 case SMB_COM_WRITE_ANDX:
225 case SMB_COM_FIND_CLOSE2:
226 case SMB_COM_LOCKING_ANDX:
230 unload_nls(nls_codepage);
234 /* Allocate and return pointer to an SMB request buffer, and set basic
235 SMB information in the SMB header. If the return code is zero, this
236 function must have filled in request_buf pointer */
238 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
243 rc = cifs_reconnect_tcon(tcon, smb_command);
247 *request_buf = cifs_small_buf_get();
248 if (*request_buf == NULL) {
249 /* BB should we add a retry in here if not a writepage? */
253 header_assemble((struct smb_hdr *) *request_buf, smb_command,
257 cifs_stats_inc(&tcon->num_smbs_sent);
263 small_smb_init_no_tc(const int smb_command, const int wct,
264 struct cifs_ses *ses, void **request_buf)
267 struct smb_hdr *buffer;
269 rc = small_smb_init(smb_command, wct, NULL, request_buf);
273 buffer = (struct smb_hdr *)*request_buf;
274 buffer->Mid = get_next_mid(ses->server);
275 if (ses->capabilities & CAP_UNICODE)
276 buffer->Flags2 |= SMBFLG2_UNICODE;
277 if (ses->capabilities & CAP_STATUS32)
278 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
280 /* uid, tid can stay at zero as set in header assemble */
282 /* BB add support for turning on the signing when
283 this function is used after 1st of session setup requests */
288 /* If the return code is zero, this function must fill in request_buf pointer */
290 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
291 void **request_buf, void **response_buf)
293 *request_buf = cifs_buf_get();
294 if (*request_buf == NULL) {
295 /* BB should we add a retry in here if not a writepage? */
298 /* Although the original thought was we needed the response buf for */
299 /* potential retries of smb operations it turns out we can determine */
300 /* from the mid flags when the request buffer can be resent without */
301 /* having to use a second distinct buffer for the response */
303 *response_buf = *request_buf;
305 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
309 cifs_stats_inc(&tcon->num_smbs_sent);
314 /* If the return code is zero, this function must fill in request_buf pointer */
316 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
317 void **request_buf, void **response_buf)
321 rc = cifs_reconnect_tcon(tcon, smb_command);
325 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
329 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
330 void **request_buf, void **response_buf)
332 if (tcon->ses->need_reconnect || tcon->need_reconnect)
335 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
338 static int validate_t2(struct smb_t2_rsp *pSMB)
340 unsigned int total_size;
342 /* check for plausible wct */
343 if (pSMB->hdr.WordCount < 10)
346 /* check for parm and data offset going beyond end of smb */
347 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
348 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
351 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
352 if (total_size >= 512)
355 /* check that bcc is at least as big as parms + data, and that it is
356 * less than negotiated smb buffer
358 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
359 if (total_size > get_bcc(&pSMB->hdr) ||
360 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
365 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
366 sizeof(struct smb_t2_rsp) + 16);
371 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
374 NEGOTIATE_RSP *pSMBr;
378 struct TCP_Server_Info *server;
380 unsigned int secFlags;
383 server = ses->server;
388 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
389 (void **) &pSMB, (void **) &pSMBr);
393 /* if any of auth flags (ie not sign or seal) are overriden use them */
394 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
395 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
396 else /* if override flags set only sign/seal OR them with global auth */
397 secFlags = global_secflags | ses->overrideSecFlg;
399 cFYI(1, "secFlags 0x%x", secFlags);
401 pSMB->hdr.Mid = get_next_mid(server);
402 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
404 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
405 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
406 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
407 cFYI(1, "Kerberos only mechanism, enable extended security");
408 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
409 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
410 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
411 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
412 cFYI(1, "NTLMSSP only mechanism, enable extended security");
413 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
417 for (i = 0; i < CIFS_NUM_PROT; i++) {
418 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
419 count += strlen(protocols[i].name) + 1;
420 /* null at end of source and target buffers anyway */
422 inc_rfc1001_len(pSMB, count);
423 pSMB->ByteCount = cpu_to_le16(count);
425 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
426 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
430 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
431 cFYI(1, "Dialect: %d", server->dialect);
432 /* Check wct = 1 error case */
433 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
434 /* core returns wct = 1, but we do not ask for core - otherwise
435 small wct just comes when dialect index is -1 indicating we
436 could not negotiate a common dialect */
439 #ifdef CONFIG_CIFS_WEAK_PW_HASH
440 } else if ((pSMBr->hdr.WordCount == 13)
441 && ((server->dialect == LANMAN_PROT)
442 || (server->dialect == LANMAN2_PROT))) {
444 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
446 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
447 (secFlags & CIFSSEC_MAY_PLNTXT))
448 server->secType = LANMAN;
450 cERROR(1, "mount failed weak security disabled"
451 " in /proc/fs/cifs/SecurityFlags");
455 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
456 server->maxReq = min_t(unsigned int,
457 le16_to_cpu(rsp->MaxMpxCount),
459 set_credits(server, server->maxReq);
460 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
461 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
462 /* even though we do not use raw we might as well set this
463 accurately, in case we ever find a need for it */
464 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
465 server->max_rw = 0xFF00;
466 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
468 server->max_rw = 0;/* do not need to use raw anyway */
469 server->capabilities = CAP_MPX_MODE;
471 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
473 /* OS/2 often does not set timezone therefore
474 * we must use server time to calc time zone.
475 * Could deviate slightly from the right zone.
476 * Smallest defined timezone difference is 15 minutes
477 * (i.e. Nepal). Rounding up/down is done to match
480 int val, seconds, remain, result;
481 struct timespec ts, utc;
483 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
484 rsp->SrvTime.Time, 0);
485 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
486 (int)ts.tv_sec, (int)utc.tv_sec,
487 (int)(utc.tv_sec - ts.tv_sec));
488 val = (int)(utc.tv_sec - ts.tv_sec);
490 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
491 remain = seconds % MIN_TZ_ADJ;
492 if (remain >= (MIN_TZ_ADJ / 2))
493 result += MIN_TZ_ADJ;
496 server->timeAdj = result;
498 server->timeAdj = (int)tmp;
499 server->timeAdj *= 60; /* also in seconds */
501 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
504 /* BB get server time for time conversions and add
505 code to use it and timezone since this is not UTC */
507 if (rsp->EncryptionKeyLength ==
508 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
509 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
510 CIFS_CRYPTO_KEY_SIZE);
511 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
512 rc = -EIO; /* need cryptkey unless plain text */
516 cFYI(1, "LANMAN negotiated");
517 /* we will not end up setting signing flags - as no signing
518 was in LANMAN and server did not return the flags on */
520 #else /* weak security disabled */
521 } else if (pSMBr->hdr.WordCount == 13) {
522 cERROR(1, "mount failed, cifs module not built "
523 "with CIFS_WEAK_PW_HASH support");
525 #endif /* WEAK_PW_HASH */
527 } else if (pSMBr->hdr.WordCount != 17) {
532 /* else wct == 17 NTLM */
533 server->sec_mode = pSMBr->SecurityMode;
534 if ((server->sec_mode & SECMODE_USER) == 0)
535 cFYI(1, "share mode security");
537 if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
538 #ifdef CONFIG_CIFS_WEAK_PW_HASH
539 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
540 #endif /* CIFS_WEAK_PW_HASH */
541 cERROR(1, "Server requests plain text password"
542 " but client support disabled");
544 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
545 server->secType = NTLMv2;
546 else if (secFlags & CIFSSEC_MAY_NTLM)
547 server->secType = NTLM;
548 else if (secFlags & CIFSSEC_MAY_NTLMV2)
549 server->secType = NTLMv2;
550 else if (secFlags & CIFSSEC_MAY_KRB5)
551 server->secType = Kerberos;
552 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
553 server->secType = RawNTLMSSP;
554 else if (secFlags & CIFSSEC_MAY_LANMAN)
555 server->secType = LANMAN;
558 cERROR(1, "Invalid security type");
561 /* else ... any others ...? */
563 /* one byte, so no need to convert this or EncryptionKeyLen from
565 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
567 set_credits(server, server->maxReq);
568 /* probably no need to store and check maxvcs */
569 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
570 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
571 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
572 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
573 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
574 server->timeAdj *= 60;
575 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
576 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
577 CIFS_CRYPTO_KEY_SIZE);
578 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
579 server->capabilities & CAP_EXTENDED_SECURITY) &&
580 (pSMBr->EncryptionKeyLength == 0)) {
581 /* decode security blob */
582 count = get_bcc(&pSMBr->hdr);
587 spin_lock(&cifs_tcp_ses_lock);
588 if (server->srv_count > 1) {
589 spin_unlock(&cifs_tcp_ses_lock);
590 if (memcmp(server->server_GUID,
591 pSMBr->u.extended_response.
593 cFYI(1, "server UID changed");
594 memcpy(server->server_GUID,
595 pSMBr->u.extended_response.GUID,
599 spin_unlock(&cifs_tcp_ses_lock);
600 memcpy(server->server_GUID,
601 pSMBr->u.extended_response.GUID, 16);
605 server->secType = RawNTLMSSP;
607 rc = decode_negTokenInit(pSMBr->u.extended_response.
608 SecurityBlob, count - 16,
614 if (server->secType == Kerberos) {
615 if (!server->sec_kerberos &&
616 !server->sec_mskerberos)
618 } else if (server->secType == RawNTLMSSP) {
619 if (!server->sec_ntlmssp)
624 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
625 rc = -EIO; /* no crypt key only if plain text pwd */
628 server->capabilities &= ~CAP_EXTENDED_SECURITY;
630 #ifdef CONFIG_CIFS_WEAK_PW_HASH
633 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
634 /* MUST_SIGN already includes the MAY_SIGN FLAG
635 so if this is zero it means that signing is disabled */
636 cFYI(1, "Signing disabled");
637 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
638 cERROR(1, "Server requires "
639 "packet signing to be enabled in "
640 "/proc/fs/cifs/SecurityFlags.");
644 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
645 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
646 /* signing required */
647 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
648 if ((server->sec_mode &
649 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
650 cERROR(1, "signing required but server lacks support");
653 server->sec_mode |= SECMODE_SIGN_REQUIRED;
655 /* signing optional ie CIFSSEC_MAY_SIGN */
656 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
658 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
662 cifs_buf_release(pSMB);
664 cFYI(1, "negprot rc %d", rc);
669 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
671 struct smb_hdr *smb_buffer;
674 cFYI(1, "In tree disconnect");
676 /* BB: do we need to check this? These should never be NULL. */
677 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
681 * No need to return error on this operation if tid invalidated and
682 * closed on server already e.g. due to tcp session crashing. Also,
683 * the tcon is no longer on the list, so no need to take lock before
686 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
689 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
690 (void **)&smb_buffer);
694 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
696 cFYI(1, "Tree disconnect failed %d", rc);
698 /* No need to return error on this operation if tid invalidated and
699 closed on server already e.g. due to tcp session crashing */
707 * This is a no-op for now. We're not really interested in the reply, but
708 * rather in the fact that the server sent one and that server->lstrp
711 * FIXME: maybe we should consider checking that the reply matches request?
714 cifs_echo_callback(struct mid_q_entry *mid)
716 struct TCP_Server_Info *server = mid->callback_data;
718 DeleteMidQEntry(mid);
719 add_credits(server, 1, CIFS_ECHO_OP);
723 CIFSSMBEcho(struct TCP_Server_Info *server)
729 cFYI(1, "In echo request");
731 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
735 /* set up echo request */
736 smb->hdr.Tid = 0xffff;
737 smb->hdr.WordCount = 1;
738 put_unaligned_le16(1, &smb->EchoCount);
739 put_bcc(1, &smb->hdr);
741 inc_rfc1001_len(smb, 3);
743 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
745 rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
746 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
748 cFYI(1, "Echo request failed: %d", rc);
750 cifs_small_buf_release(smb);
756 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
758 LOGOFF_ANDX_REQ *pSMB;
761 cFYI(1, "In SMBLogoff for session disconnect");
764 * BB: do we need to check validity of ses and server? They should
765 * always be valid since we have an active reference. If not, that
766 * should probably be a BUG()
768 if (!ses || !ses->server)
771 mutex_lock(&ses->session_mutex);
772 if (ses->need_reconnect)
773 goto session_already_dead; /* no need to send SMBlogoff if uid
774 already closed due to reconnect */
775 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
777 mutex_unlock(&ses->session_mutex);
781 pSMB->hdr.Mid = get_next_mid(ses->server);
783 if (ses->server->sec_mode &
784 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
785 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
787 pSMB->hdr.Uid = ses->Suid;
789 pSMB->AndXCommand = 0xFF;
790 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
791 session_already_dead:
792 mutex_unlock(&ses->session_mutex);
794 /* if session dead then we do not need to do ulogoff,
795 since server closed smb session, no sense reporting
803 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
804 const char *fileName, __u16 type,
805 const struct nls_table *nls_codepage, int remap)
807 TRANSACTION2_SPI_REQ *pSMB = NULL;
808 TRANSACTION2_SPI_RSP *pSMBr = NULL;
809 struct unlink_psx_rq *pRqD;
812 int bytes_returned = 0;
813 __u16 params, param_offset, offset, byte_count;
815 cFYI(1, "In POSIX delete");
817 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
822 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
824 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
825 PATH_MAX, nls_codepage, remap);
826 name_len++; /* trailing null */
828 } else { /* BB add path length overrun check */
829 name_len = strnlen(fileName, PATH_MAX);
830 name_len++; /* trailing null */
831 strncpy(pSMB->FileName, fileName, name_len);
834 params = 6 + name_len;
835 pSMB->MaxParameterCount = cpu_to_le16(2);
836 pSMB->MaxDataCount = 0; /* BB double check this with jra */
837 pSMB->MaxSetupCount = 0;
842 param_offset = offsetof(struct smb_com_transaction2_spi_req,
843 InformationLevel) - 4;
844 offset = param_offset + params;
846 /* Setup pointer to Request Data (inode type) */
847 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
848 pRqD->type = cpu_to_le16(type);
849 pSMB->ParameterOffset = cpu_to_le16(param_offset);
850 pSMB->DataOffset = cpu_to_le16(offset);
851 pSMB->SetupCount = 1;
853 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
854 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
856 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
857 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
858 pSMB->ParameterCount = cpu_to_le16(params);
859 pSMB->TotalParameterCount = pSMB->ParameterCount;
860 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
862 inc_rfc1001_len(pSMB, byte_count);
863 pSMB->ByteCount = cpu_to_le16(byte_count);
864 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
865 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
867 cFYI(1, "Posix delete returned %d", rc);
868 cifs_buf_release(pSMB);
870 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
879 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
880 struct cifs_sb_info *cifs_sb)
882 DELETE_FILE_REQ *pSMB = NULL;
883 DELETE_FILE_RSP *pSMBr = NULL;
887 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
890 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
895 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
896 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
897 PATH_MAX, cifs_sb->local_nls,
899 name_len++; /* trailing null */
901 } else { /* BB improve check for buffer overruns BB */
902 name_len = strnlen(name, PATH_MAX);
903 name_len++; /* trailing null */
904 strncpy(pSMB->fileName, name, name_len);
906 pSMB->SearchAttributes =
907 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
908 pSMB->BufferFormat = 0x04;
909 inc_rfc1001_len(pSMB, name_len + 1);
910 pSMB->ByteCount = cpu_to_le16(name_len + 1);
911 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
912 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
913 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
915 cFYI(1, "Error in RMFile = %d", rc);
917 cifs_buf_release(pSMB);
925 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
926 struct cifs_sb_info *cifs_sb)
928 DELETE_DIRECTORY_REQ *pSMB = NULL;
929 DELETE_DIRECTORY_RSP *pSMBr = NULL;
933 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
935 cFYI(1, "In CIFSSMBRmDir");
937 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
942 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
943 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
944 PATH_MAX, cifs_sb->local_nls,
946 name_len++; /* trailing null */
948 } else { /* BB improve check for buffer overruns BB */
949 name_len = strnlen(name, PATH_MAX);
950 name_len++; /* trailing null */
951 strncpy(pSMB->DirName, name, name_len);
954 pSMB->BufferFormat = 0x04;
955 inc_rfc1001_len(pSMB, 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->stats.cifs_stats.num_rmdirs);
961 cFYI(1, "Error in RMDir = %d", rc);
963 cifs_buf_release(pSMB);
970 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
971 struct cifs_sb_info *cifs_sb)
974 CREATE_DIRECTORY_REQ *pSMB = NULL;
975 CREATE_DIRECTORY_RSP *pSMBr = NULL;
978 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
980 cFYI(1, "In CIFSSMBMkDir");
982 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
987 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
988 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
989 PATH_MAX, cifs_sb->local_nls,
991 name_len++; /* trailing null */
993 } else { /* BB improve check for buffer overruns BB */
994 name_len = strnlen(name, PATH_MAX);
995 name_len++; /* trailing null */
996 strncpy(pSMB->DirName, name, name_len);
999 pSMB->BufferFormat = 0x04;
1000 inc_rfc1001_len(pSMB, name_len + 1);
1001 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1002 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1003 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1004 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1006 cFYI(1, "Error in Mkdir = %d", rc);
1008 cifs_buf_release(pSMB);
1015 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1016 __u32 posix_flags, __u64 mode, __u16 *netfid,
1017 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1018 const char *name, const struct nls_table *nls_codepage,
1021 TRANSACTION2_SPI_REQ *pSMB = NULL;
1022 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1025 int bytes_returned = 0;
1026 __u16 params, param_offset, offset, byte_count, count;
1027 OPEN_PSX_REQ *pdata;
1028 OPEN_PSX_RSP *psx_rsp;
1030 cFYI(1, "In POSIX Create");
1032 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1037 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1039 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1040 PATH_MAX, nls_codepage, remap);
1041 name_len++; /* trailing null */
1043 } else { /* BB improve the check for buffer overruns BB */
1044 name_len = strnlen(name, PATH_MAX);
1045 name_len++; /* trailing null */
1046 strncpy(pSMB->FileName, name, name_len);
1049 params = 6 + name_len;
1050 count = sizeof(OPEN_PSX_REQ);
1051 pSMB->MaxParameterCount = cpu_to_le16(2);
1052 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1053 pSMB->MaxSetupCount = 0;
1057 pSMB->Reserved2 = 0;
1058 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1059 InformationLevel) - 4;
1060 offset = param_offset + params;
1061 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1062 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1063 pdata->Permissions = cpu_to_le64(mode);
1064 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1065 pdata->OpenFlags = cpu_to_le32(*pOplock);
1066 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1067 pSMB->DataOffset = cpu_to_le16(offset);
1068 pSMB->SetupCount = 1;
1069 pSMB->Reserved3 = 0;
1070 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1071 byte_count = 3 /* pad */ + params + count;
1073 pSMB->DataCount = cpu_to_le16(count);
1074 pSMB->ParameterCount = cpu_to_le16(params);
1075 pSMB->TotalDataCount = pSMB->DataCount;
1076 pSMB->TotalParameterCount = pSMB->ParameterCount;
1077 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1078 pSMB->Reserved4 = 0;
1079 inc_rfc1001_len(pSMB, byte_count);
1080 pSMB->ByteCount = cpu_to_le16(byte_count);
1081 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1082 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1084 cFYI(1, "Posix create returned %d", rc);
1085 goto psx_create_err;
1088 cFYI(1, "copying inode info");
1089 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1091 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1092 rc = -EIO; /* bad smb */
1093 goto psx_create_err;
1096 /* copy return information to pRetData */
1097 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1098 + le16_to_cpu(pSMBr->t2.DataOffset));
1100 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1102 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1103 /* Let caller know file was created so we can set the mode. */
1104 /* Do we care about the CreateAction in any other cases? */
1105 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1106 *pOplock |= CIFS_CREATE_ACTION;
1107 /* check to make sure response data is there */
1108 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1109 pRetData->Type = cpu_to_le32(-1); /* unknown */
1110 cFYI(DBG2, "unknown type");
1112 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1113 + sizeof(FILE_UNIX_BASIC_INFO)) {
1114 cERROR(1, "Open response data too small");
1115 pRetData->Type = cpu_to_le32(-1);
1116 goto psx_create_err;
1118 memcpy((char *) pRetData,
1119 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1120 sizeof(FILE_UNIX_BASIC_INFO));
1124 cifs_buf_release(pSMB);
1126 if (posix_flags & SMB_O_DIRECTORY)
1127 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1129 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1137 static __u16 convert_disposition(int disposition)
1141 switch (disposition) {
1142 case FILE_SUPERSEDE:
1143 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1146 ofun = SMBOPEN_OAPPEND;
1149 ofun = SMBOPEN_OCREATE;
1152 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1154 case FILE_OVERWRITE:
1155 ofun = SMBOPEN_OTRUNC;
1157 case FILE_OVERWRITE_IF:
1158 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1161 cFYI(1, "unknown disposition %d", disposition);
1162 ofun = SMBOPEN_OAPPEND; /* regular open */
1168 access_flags_to_smbopen_mode(const int access_flags)
1170 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1172 if (masked_flags == GENERIC_READ)
1173 return SMBOPEN_READ;
1174 else if (masked_flags == GENERIC_WRITE)
1175 return SMBOPEN_WRITE;
1177 /* just go for read/write */
1178 return SMBOPEN_READWRITE;
1182 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1183 const char *fileName, const int openDisposition,
1184 const int access_flags, const int create_options, __u16 *netfid,
1185 int *pOplock, FILE_ALL_INFO *pfile_info,
1186 const struct nls_table *nls_codepage, int remap)
1189 OPENX_REQ *pSMB = NULL;
1190 OPENX_RSP *pSMBr = NULL;
1196 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1201 pSMB->AndXCommand = 0xFF; /* none */
1203 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1204 count = 1; /* account for one byte pad to word boundary */
1206 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1207 fileName, PATH_MAX, nls_codepage, remap);
1208 name_len++; /* trailing null */
1210 } else { /* BB improve check for buffer overruns BB */
1211 count = 0; /* no pad */
1212 name_len = strnlen(fileName, PATH_MAX);
1213 name_len++; /* trailing null */
1214 strncpy(pSMB->fileName, fileName, name_len);
1216 if (*pOplock & REQ_OPLOCK)
1217 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1218 else if (*pOplock & REQ_BATCHOPLOCK)
1219 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1221 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1222 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1223 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1224 /* set file as system file if special file such
1225 as fifo and server expecting SFU style and
1226 no Unix extensions */
1228 if (create_options & CREATE_OPTION_SPECIAL)
1229 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1230 else /* BB FIXME BB */
1231 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1233 if (create_options & CREATE_OPTION_READONLY)
1234 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1237 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1238 CREATE_OPTIONS_MASK); */
1239 /* BB FIXME END BB */
1241 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1242 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1244 inc_rfc1001_len(pSMB, count);
1246 pSMB->ByteCount = cpu_to_le16(count);
1247 /* long_op set to 1 to allow for oplock break timeouts */
1248 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1249 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1250 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1252 cFYI(1, "Error in Open = %d", rc);
1254 /* BB verify if wct == 15 */
1256 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1258 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1259 /* Let caller know file was created so we can set the mode. */
1260 /* Do we care about the CreateAction in any other cases? */
1262 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1263 *pOplock |= CIFS_CREATE_ACTION; */
1267 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1268 pfile_info->LastAccessTime = 0; /* BB fixme */
1269 pfile_info->LastWriteTime = 0; /* BB fixme */
1270 pfile_info->ChangeTime = 0; /* BB fixme */
1271 pfile_info->Attributes =
1272 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1273 /* the file_info buf is endian converted by caller */
1274 pfile_info->AllocationSize =
1275 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1276 pfile_info->EndOfFile = pfile_info->AllocationSize;
1277 pfile_info->NumberOfLinks = cpu_to_le32(1);
1278 pfile_info->DeletePending = 0;
1282 cifs_buf_release(pSMB);
1289 CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1290 const char *fileName, const int openDisposition,
1291 const int access_flags, const int create_options, __u16 *netfid,
1292 int *pOplock, FILE_ALL_INFO *pfile_info,
1293 const struct nls_table *nls_codepage, int remap)
1296 OPEN_REQ *pSMB = NULL;
1297 OPEN_RSP *pSMBr = NULL;
1303 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1308 pSMB->AndXCommand = 0xFF; /* none */
1310 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1311 count = 1; /* account for one byte pad to word boundary */
1313 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1314 fileName, PATH_MAX, nls_codepage, remap);
1315 name_len++; /* trailing null */
1317 pSMB->NameLength = cpu_to_le16(name_len);
1318 } else { /* BB improve check for buffer overruns BB */
1319 count = 0; /* no pad */
1320 name_len = strnlen(fileName, PATH_MAX);
1321 name_len++; /* trailing null */
1322 pSMB->NameLength = cpu_to_le16(name_len);
1323 strncpy(pSMB->fileName, fileName, name_len);
1325 if (*pOplock & REQ_OPLOCK)
1326 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1327 else if (*pOplock & REQ_BATCHOPLOCK)
1328 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1329 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1330 pSMB->AllocationSize = 0;
1331 /* set file as system file if special file such
1332 as fifo and server expecting SFU style and
1333 no Unix extensions */
1334 if (create_options & CREATE_OPTION_SPECIAL)
1335 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1337 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1339 /* XP does not handle ATTR_POSIX_SEMANTICS */
1340 /* but it helps speed up case sensitive checks for other
1341 servers such as Samba */
1342 if (tcon->ses->capabilities & CAP_UNIX)
1343 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1345 if (create_options & CREATE_OPTION_READONLY)
1346 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1348 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1349 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1350 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1351 /* BB Expirement with various impersonation levels and verify */
1352 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1353 pSMB->SecurityFlags =
1354 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1357 inc_rfc1001_len(pSMB, count);
1359 pSMB->ByteCount = cpu_to_le16(count);
1360 /* long_op set to 1 to allow for oplock break timeouts */
1361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1362 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1363 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1365 cFYI(1, "Error in Open = %d", rc);
1367 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1368 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1369 /* Let caller know file was created so we can set the mode. */
1370 /* Do we care about the CreateAction in any other cases? */
1371 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1372 *pOplock |= CIFS_CREATE_ACTION;
1374 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1375 36 /* CreationTime to Attributes */);
1376 /* the file_info buf is endian converted by caller */
1377 pfile_info->AllocationSize = pSMBr->AllocationSize;
1378 pfile_info->EndOfFile = pSMBr->EndOfFile;
1379 pfile_info->NumberOfLinks = cpu_to_le32(1);
1380 pfile_info->DeletePending = 0;
1384 cifs_buf_release(pSMB);
1391 * Discard any remaining data in the current SMB. To do this, we borrow the
1395 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1397 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1398 int remaining = rfclen + 4 - server->total_read;
1399 struct cifs_readdata *rdata = mid->callback_data;
1401 while (remaining > 0) {
1404 length = cifs_read_from_socket(server, server->bigbuf,
1405 min_t(unsigned int, remaining,
1406 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1409 server->total_read += length;
1410 remaining -= length;
1413 dequeue_mid(mid, rdata->result);
1418 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1421 unsigned int data_offset, data_len;
1422 struct cifs_readdata *rdata = mid->callback_data;
1423 char *buf = server->smallbuf;
1424 unsigned int buflen = get_rfc1002_length(buf) + 4;
1426 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1427 mid->mid, rdata->offset, rdata->bytes);
1430 * read the rest of READ_RSP header (sans Data array), or whatever we
1431 * can if there's not enough data. At this point, we've read down to
1434 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1435 HEADER_SIZE(server) + 1;
1437 rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1438 rdata->iov[0].iov_len = len;
1440 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1443 server->total_read += length;
1445 /* Was the SMB read successful? */
1446 rdata->result = server->ops->map_error(buf, false);
1447 if (rdata->result != 0) {
1448 cFYI(1, "%s: server returned error %d", __func__,
1450 return cifs_readv_discard(server, mid);
1453 /* Is there enough to get to the rest of the READ_RSP header? */
1454 if (server->total_read < server->vals->read_rsp_size) {
1455 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1456 __func__, server->total_read,
1457 server->vals->read_rsp_size);
1458 rdata->result = -EIO;
1459 return cifs_readv_discard(server, mid);
1462 data_offset = server->ops->read_data_offset(buf) + 4;
1463 if (data_offset < server->total_read) {
1465 * win2k8 sometimes sends an offset of 0 when the read
1466 * is beyond the EOF. Treat it as if the data starts just after
1469 cFYI(1, "%s: data offset (%u) inside read response header",
1470 __func__, data_offset);
1471 data_offset = server->total_read;
1472 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1473 /* data_offset is beyond the end of smallbuf */
1474 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1475 __func__, data_offset);
1476 rdata->result = -EIO;
1477 return cifs_readv_discard(server, mid);
1480 cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1481 server->total_read, data_offset);
1483 len = data_offset - server->total_read;
1485 /* read any junk before data into the rest of smallbuf */
1486 rdata->iov[0].iov_base = buf + server->total_read;
1487 rdata->iov[0].iov_len = len;
1488 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1491 server->total_read += length;
1494 /* set up first iov for signature check */
1495 rdata->iov[0].iov_base = buf;
1496 rdata->iov[0].iov_len = server->total_read;
1497 cFYI(1, "0: iov_base=%p iov_len=%zu",
1498 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1500 /* how much data is in the response? */
1501 data_len = server->ops->read_data_length(buf);
1502 if (data_offset + data_len > buflen) {
1503 /* data_len is corrupt -- discard frame */
1504 rdata->result = -EIO;
1505 return cifs_readv_discard(server, mid);
1508 /* marshal up the page array */
1510 len = rdata->marshal_iov(rdata, data_len);
1514 /* issue the read if we have any iovecs left to fill */
1515 if (rdata->nr_iov > 1) {
1516 length = cifs_readv_from_socket(server, &rdata->iov[1],
1517 rdata->nr_iov - 1, len);
1520 server->total_read += length;
1525 rdata->bytes = length;
1527 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1530 /* discard anything left over */
1531 if (server->total_read < buflen)
1532 return cifs_readv_discard(server, mid);
1534 dequeue_mid(mid, false);
1539 cifs_readv_callback(struct mid_q_entry *mid)
1541 struct cifs_readdata *rdata = mid->callback_data;
1542 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1543 struct TCP_Server_Info *server = tcon->ses->server;
1544 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1545 .rq_nvec = rdata->nr_iov };
1547 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1548 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1550 switch (mid->mid_state) {
1551 case MID_RESPONSE_RECEIVED:
1552 /* result already set, check signature */
1553 if (server->sec_mode &
1554 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1557 rc = cifs_verify_signature(&rqst, server,
1558 mid->sequence_number + 1);
1560 cERROR(1, "SMB signature verification returned "
1563 /* FIXME: should this be counted toward the initiating task? */
1564 task_io_account_read(rdata->bytes);
1565 cifs_stats_bytes_read(tcon, rdata->bytes);
1567 case MID_REQUEST_SUBMITTED:
1568 case MID_RETRY_NEEDED:
1569 rdata->result = -EAGAIN;
1572 rdata->result = -EIO;
1575 queue_work(cifsiod_wq, &rdata->work);
1576 DeleteMidQEntry(mid);
1577 add_credits(server, 1, 0);
1580 /* cifs_async_readv - send an async write, and set up mid to handle result */
1582 cifs_async_readv(struct cifs_readdata *rdata)
1585 READ_REQ *smb = NULL;
1587 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1589 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1590 rdata->offset, rdata->bytes);
1592 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1595 wct = 10; /* old style read */
1596 if ((rdata->offset >> 32) > 0) {
1597 /* can not handle this big offset for old */
1602 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1606 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1607 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1609 smb->AndXCommand = 0xFF; /* none */
1610 smb->Fid = rdata->cfile->fid.netfid;
1611 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1613 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1615 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1616 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1620 /* old style read */
1621 struct smb_com_readx_req *smbr =
1622 (struct smb_com_readx_req *)smb;
1623 smbr->ByteCount = 0;
1626 /* 4 for RFC1001 length + 1 for BCC */
1627 rdata->iov[0].iov_base = smb;
1628 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1630 kref_get(&rdata->refcount);
1631 rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1632 cifs_readv_receive, cifs_readv_callback,
1636 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1638 kref_put(&rdata->refcount, cifs_readdata_release);
1640 cifs_small_buf_release(smb);
1645 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1646 unsigned int *nbytes, char **buf, int *pbuf_type)
1649 READ_REQ *pSMB = NULL;
1650 READ_RSP *pSMBr = NULL;
1651 char *pReadData = NULL;
1653 int resp_buf_type = 0;
1655 __u32 pid = io_parms->pid;
1656 __u16 netfid = io_parms->netfid;
1657 __u64 offset = io_parms->offset;
1658 struct cifs_tcon *tcon = io_parms->tcon;
1659 unsigned int count = io_parms->length;
1661 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1662 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1665 wct = 10; /* old style read */
1666 if ((offset >> 32) > 0) {
1667 /* can not handle this big offset for old */
1673 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1677 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1678 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1680 /* tcon and ses pointer are checked in smb_init */
1681 if (tcon->ses->server == NULL)
1682 return -ECONNABORTED;
1684 pSMB->AndXCommand = 0xFF; /* none */
1686 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1688 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1690 pSMB->Remaining = 0;
1691 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1692 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1694 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1696 /* old style read */
1697 struct smb_com_readx_req *pSMBW =
1698 (struct smb_com_readx_req *)pSMB;
1699 pSMBW->ByteCount = 0;
1702 iov[0].iov_base = (char *)pSMB;
1703 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1704 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1705 &resp_buf_type, CIFS_LOG_ERROR);
1706 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1707 pSMBr = (READ_RSP *)iov[0].iov_base;
1709 cERROR(1, "Send error in read = %d", rc);
1711 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1712 data_length = data_length << 16;
1713 data_length += le16_to_cpu(pSMBr->DataLength);
1714 *nbytes = data_length;
1716 /*check that DataLength would not go beyond end of SMB */
1717 if ((data_length > CIFSMaxBufSize)
1718 || (data_length > count)) {
1719 cFYI(1, "bad length %d for count %d",
1720 data_length, count);
1724 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1725 le16_to_cpu(pSMBr->DataOffset);
1726 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1727 cERROR(1, "Faulting on read rc = %d",rc);
1729 }*/ /* can not use copy_to_user when using page cache*/
1731 memcpy(*buf, pReadData, data_length);
1735 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1737 if (resp_buf_type == CIFS_SMALL_BUFFER)
1738 cifs_small_buf_release(iov[0].iov_base);
1739 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1740 cifs_buf_release(iov[0].iov_base);
1741 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1742 /* return buffer to caller to free */
1743 *buf = iov[0].iov_base;
1744 if (resp_buf_type == CIFS_SMALL_BUFFER)
1745 *pbuf_type = CIFS_SMALL_BUFFER;
1746 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1747 *pbuf_type = CIFS_LARGE_BUFFER;
1748 } /* else no valid buffer on return - leave as null */
1750 /* Note: On -EAGAIN error only caller can retry on handle based calls
1751 since file handle passed in no longer valid */
1757 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1758 unsigned int *nbytes, const char *buf,
1759 const char __user *ubuf, const int long_op)
1762 WRITE_REQ *pSMB = NULL;
1763 WRITE_RSP *pSMBr = NULL;
1764 int bytes_returned, wct;
1767 __u32 pid = io_parms->pid;
1768 __u16 netfid = io_parms->netfid;
1769 __u64 offset = io_parms->offset;
1770 struct cifs_tcon *tcon = io_parms->tcon;
1771 unsigned int count = io_parms->length;
1775 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1776 if (tcon->ses == NULL)
1777 return -ECONNABORTED;
1779 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1783 if ((offset >> 32) > 0) {
1784 /* can not handle big offset for old srv */
1789 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1794 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1795 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1797 /* tcon and ses pointer are checked in smb_init */
1798 if (tcon->ses->server == NULL)
1799 return -ECONNABORTED;
1801 pSMB->AndXCommand = 0xFF; /* none */
1803 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1805 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1807 pSMB->Reserved = 0xFFFFFFFF;
1808 pSMB->WriteMode = 0;
1809 pSMB->Remaining = 0;
1811 /* Can increase buffer size if buffer is big enough in some cases ie we
1812 can send more if LARGE_WRITE_X capability returned by the server and if
1813 our buffer is big enough or if we convert to iovecs on socket writes
1814 and eliminate the copy to the CIFS buffer */
1815 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1816 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1818 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1822 if (bytes_sent > count)
1825 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1827 memcpy(pSMB->Data, buf, bytes_sent);
1829 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1830 cifs_buf_release(pSMB);
1833 } else if (count != 0) {
1835 cifs_buf_release(pSMB);
1837 } /* else setting file size with write of zero bytes */
1839 byte_count = bytes_sent + 1; /* pad */
1840 else /* wct == 12 */
1841 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1843 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1844 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1845 inc_rfc1001_len(pSMB, byte_count);
1848 pSMB->ByteCount = cpu_to_le16(byte_count);
1849 else { /* old style write has byte count 4 bytes earlier
1851 struct smb_com_writex_req *pSMBW =
1852 (struct smb_com_writex_req *)pSMB;
1853 pSMBW->ByteCount = cpu_to_le16(byte_count);
1856 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1857 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1858 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1860 cFYI(1, "Send error in write = %d", rc);
1862 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1863 *nbytes = (*nbytes) << 16;
1864 *nbytes += le16_to_cpu(pSMBr->Count);
1867 * Mask off high 16 bits when bytes written as returned by the
1868 * server is greater than bytes requested by the client. Some
1869 * OS/2 servers are known to set incorrect CountHigh values.
1871 if (*nbytes > count)
1875 cifs_buf_release(pSMB);
1877 /* Note: On -EAGAIN error only caller can retry on handle based calls
1878 since file handle passed in no longer valid */
1884 cifs_writedata_release(struct kref *refcount)
1886 struct cifs_writedata *wdata = container_of(refcount,
1887 struct cifs_writedata, refcount);
1890 cifsFileInfo_put(wdata->cfile);
1896 * Write failed with a retryable error. Resend the write request. It's also
1897 * possible that the page was redirtied so re-clean the page.
1900 cifs_writev_requeue(struct cifs_writedata *wdata)
1903 struct inode *inode = wdata->cfile->dentry->d_inode;
1904 struct TCP_Server_Info *server;
1906 for (i = 0; i < wdata->nr_pages; i++) {
1907 lock_page(wdata->pages[i]);
1908 clear_page_dirty_for_io(wdata->pages[i]);
1912 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1913 rc = server->ops->async_writev(wdata);
1914 } while (rc == -EAGAIN);
1916 for (i = 0; i < wdata->nr_pages; i++) {
1918 SetPageError(wdata->pages[i]);
1919 unlock_page(wdata->pages[i]);
1922 mapping_set_error(inode->i_mapping, rc);
1923 kref_put(&wdata->refcount, cifs_writedata_release);
1927 cifs_writev_complete(struct work_struct *work)
1929 struct cifs_writedata *wdata = container_of(work,
1930 struct cifs_writedata, work);
1931 struct inode *inode = wdata->cfile->dentry->d_inode;
1934 if (wdata->result == 0) {
1935 spin_lock(&inode->i_lock);
1936 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1937 spin_unlock(&inode->i_lock);
1938 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1940 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1941 return cifs_writev_requeue(wdata);
1943 for (i = 0; i < wdata->nr_pages; i++) {
1944 struct page *page = wdata->pages[i];
1945 if (wdata->result == -EAGAIN)
1946 __set_page_dirty_nobuffers(page);
1947 else if (wdata->result < 0)
1949 end_page_writeback(page);
1950 page_cache_release(page);
1952 if (wdata->result != -EAGAIN)
1953 mapping_set_error(inode->i_mapping, wdata->result);
1954 kref_put(&wdata->refcount, cifs_writedata_release);
1957 struct cifs_writedata *
1958 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1960 struct cifs_writedata *wdata;
1962 /* this would overflow */
1963 if (nr_pages == 0) {
1964 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1968 /* writedata + number of page pointers */
1969 wdata = kzalloc(sizeof(*wdata) +
1970 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1971 if (wdata != NULL) {
1972 kref_init(&wdata->refcount);
1973 INIT_LIST_HEAD(&wdata->list);
1974 init_completion(&wdata->done);
1975 INIT_WORK(&wdata->work, complete);
1981 * Check the mid_state and signature on received buffer (if any), and queue the
1982 * workqueue completion task.
1985 cifs_writev_callback(struct mid_q_entry *mid)
1987 struct cifs_writedata *wdata = mid->callback_data;
1988 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1989 unsigned int written;
1990 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1992 switch (mid->mid_state) {
1993 case MID_RESPONSE_RECEIVED:
1994 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1995 if (wdata->result != 0)
1998 written = le16_to_cpu(smb->CountHigh);
2000 written += le16_to_cpu(smb->Count);
2002 * Mask off high 16 bits when bytes written as returned
2003 * by the server is greater than bytes requested by the
2004 * client. OS/2 servers are known to set incorrect
2007 if (written > wdata->bytes)
2010 if (written < wdata->bytes)
2011 wdata->result = -ENOSPC;
2013 wdata->bytes = written;
2015 case MID_REQUEST_SUBMITTED:
2016 case MID_RETRY_NEEDED:
2017 wdata->result = -EAGAIN;
2020 wdata->result = -EIO;
2024 queue_work(cifsiod_wq, &wdata->work);
2025 DeleteMidQEntry(mid);
2026 add_credits(tcon->ses->server, 1, 0);
2029 /* cifs_async_writev - send an async write, and set up mid to handle result */
2031 cifs_async_writev(struct cifs_writedata *wdata)
2033 int i, rc = -EACCES;
2034 WRITE_REQ *smb = NULL;
2036 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2037 struct kvec *iov = NULL;
2039 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2043 if (wdata->offset >> 32 > 0) {
2044 /* can not handle big offset for old srv */
2049 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2051 goto async_writev_out;
2053 /* 1 iov per page + 1 for header */
2054 iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2057 goto async_writev_out;
2060 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2061 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2063 smb->AndXCommand = 0xFF; /* none */
2064 smb->Fid = wdata->cfile->fid.netfid;
2065 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2067 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2068 smb->Reserved = 0xFFFFFFFF;
2073 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2075 /* 4 for RFC1001 length + 1 for BCC */
2076 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2077 iov[0].iov_base = smb;
2080 * This function should marshal up the page array into the kvec
2081 * array, reserving [0] for the header. It should kmap the pages
2082 * and set the iov_len properly for each one. It may also set
2086 wdata->marshal_iov(iov, wdata);
2089 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2091 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2092 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2095 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2096 put_bcc(wdata->bytes + 1, &smb->hdr);
2099 struct smb_com_writex_req *smbw =
2100 (struct smb_com_writex_req *)smb;
2101 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2102 put_bcc(wdata->bytes + 5, &smbw->hdr);
2103 iov[0].iov_len += 4; /* pad bigger by four bytes */
2106 kref_get(&wdata->refcount);
2107 rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2108 NULL, cifs_writev_callback, wdata, 0);
2111 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2113 kref_put(&wdata->refcount, cifs_writedata_release);
2115 /* send is done, unmap pages */
2116 for (i = 0; i < wdata->nr_pages; i++)
2117 kunmap(wdata->pages[i]);
2120 cifs_small_buf_release(smb);
2126 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2127 unsigned int *nbytes, struct kvec *iov, int n_vec)
2130 WRITE_REQ *pSMB = NULL;
2133 int resp_buf_type = 0;
2134 __u32 pid = io_parms->pid;
2135 __u16 netfid = io_parms->netfid;
2136 __u64 offset = io_parms->offset;
2137 struct cifs_tcon *tcon = io_parms->tcon;
2138 unsigned int count = io_parms->length;
2142 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2144 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2148 if ((offset >> 32) > 0) {
2149 /* can not handle big offset for old srv */
2153 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2157 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2158 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2160 /* tcon and ses pointer are checked in smb_init */
2161 if (tcon->ses->server == NULL)
2162 return -ECONNABORTED;
2164 pSMB->AndXCommand = 0xFF; /* none */
2166 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2168 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2169 pSMB->Reserved = 0xFFFFFFFF;
2170 pSMB->WriteMode = 0;
2171 pSMB->Remaining = 0;
2174 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2176 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2177 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2178 /* header + 1 byte pad */
2179 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2181 inc_rfc1001_len(pSMB, count + 1);
2182 else /* wct == 12 */
2183 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2185 pSMB->ByteCount = cpu_to_le16(count + 1);
2186 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2187 struct smb_com_writex_req *pSMBW =
2188 (struct smb_com_writex_req *)pSMB;
2189 pSMBW->ByteCount = cpu_to_le16(count + 5);
2191 iov[0].iov_base = pSMB;
2193 iov[0].iov_len = smb_hdr_len + 4;
2194 else /* wct == 12 pad bigger by four bytes */
2195 iov[0].iov_len = smb_hdr_len + 8;
2198 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
2199 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2201 cFYI(1, "Send error Write2 = %d", rc);
2202 } else if (resp_buf_type == 0) {
2203 /* presumably this can not happen, but best to be safe */
2206 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2207 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2208 *nbytes = (*nbytes) << 16;
2209 *nbytes += le16_to_cpu(pSMBr->Count);
2212 * Mask off high 16 bits when bytes written as returned by the
2213 * server is greater than bytes requested by the client. OS/2
2214 * servers are known to set incorrect CountHigh values.
2216 if (*nbytes > count)
2220 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2221 if (resp_buf_type == CIFS_SMALL_BUFFER)
2222 cifs_small_buf_release(iov[0].iov_base);
2223 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2224 cifs_buf_release(iov[0].iov_base);
2226 /* Note: On -EAGAIN error only caller can retry on handle based calls
2227 since file handle passed in no longer valid */
2232 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2233 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2234 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2237 LOCK_REQ *pSMB = NULL;
2242 cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2244 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2249 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2250 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2251 pSMB->LockType = lock_type;
2252 pSMB->AndXCommand = 0xFF; /* none */
2253 pSMB->Fid = netfid; /* netfid stays le */
2255 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2256 inc_rfc1001_len(pSMB, count);
2257 pSMB->ByteCount = cpu_to_le16(count);
2259 iov[0].iov_base = (char *)pSMB;
2260 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2261 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2262 iov[1].iov_base = (char *)buf;
2263 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2265 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2266 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2268 cFYI(1, "Send error in cifs_lockv = %d", rc);
2274 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2275 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2276 const __u64 offset, const __u32 numUnlock,
2277 const __u32 numLock, const __u8 lockType,
2278 const bool waitFlag, const __u8 oplock_level)
2281 LOCK_REQ *pSMB = NULL;
2282 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2287 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2288 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2293 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2294 /* no response expected */
2295 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2297 } else if (waitFlag) {
2298 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2299 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2304 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2305 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2306 pSMB->LockType = lockType;
2307 pSMB->OplockLevel = oplock_level;
2308 pSMB->AndXCommand = 0xFF; /* none */
2309 pSMB->Fid = smb_file_id; /* netfid stays le */
2311 if ((numLock != 0) || (numUnlock != 0)) {
2312 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2313 /* BB where to store pid high? */
2314 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2315 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2316 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2317 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2318 count = sizeof(LOCKING_ANDX_RANGE);
2323 inc_rfc1001_len(pSMB, count);
2324 pSMB->ByteCount = cpu_to_le16(count);
2327 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2328 (struct smb_hdr *) pSMB, &bytes_returned);
2329 cifs_small_buf_release(pSMB);
2331 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2332 /* SMB buffer freed by function above */
2334 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2336 cFYI(1, "Send error in Lock = %d", rc);
2338 /* Note: On -EAGAIN error only caller can retry on handle based calls
2339 since file handle passed in no longer valid */
2344 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2345 const __u16 smb_file_id, const __u32 netpid,
2346 const loff_t start_offset, const __u64 len,
2347 struct file_lock *pLockData, const __u16 lock_type,
2348 const bool waitFlag)
2350 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2351 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2352 struct cifs_posix_lock *parm_data;
2355 int bytes_returned = 0;
2356 int resp_buf_type = 0;
2357 __u16 params, param_offset, offset, byte_count, count;
2360 cFYI(1, "Posix Lock");
2362 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2367 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2370 pSMB->MaxSetupCount = 0;
2373 pSMB->Reserved2 = 0;
2374 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2375 offset = param_offset + params;
2377 count = sizeof(struct cifs_posix_lock);
2378 pSMB->MaxParameterCount = cpu_to_le16(2);
2379 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2380 pSMB->SetupCount = 1;
2381 pSMB->Reserved3 = 0;
2383 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2385 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2386 byte_count = 3 /* pad */ + params + count;
2387 pSMB->DataCount = cpu_to_le16(count);
2388 pSMB->ParameterCount = cpu_to_le16(params);
2389 pSMB->TotalDataCount = pSMB->DataCount;
2390 pSMB->TotalParameterCount = pSMB->ParameterCount;
2391 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2392 parm_data = (struct cifs_posix_lock *)
2393 (((char *) &pSMB->hdr.Protocol) + offset);
2395 parm_data->lock_type = cpu_to_le16(lock_type);
2397 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2398 parm_data->lock_flags = cpu_to_le16(1);
2399 pSMB->Timeout = cpu_to_le32(-1);
2403 parm_data->pid = cpu_to_le32(netpid);
2404 parm_data->start = cpu_to_le64(start_offset);
2405 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2407 pSMB->DataOffset = cpu_to_le16(offset);
2408 pSMB->Fid = smb_file_id;
2409 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2410 pSMB->Reserved4 = 0;
2411 inc_rfc1001_len(pSMB, byte_count);
2412 pSMB->ByteCount = cpu_to_le16(byte_count);
2414 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2415 (struct smb_hdr *) pSMBr, &bytes_returned);
2417 iov[0].iov_base = (char *)pSMB;
2418 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2419 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2420 &resp_buf_type, timeout);
2421 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2422 not try to free it twice below on exit */
2423 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2427 cFYI(1, "Send error in Posix Lock = %d", rc);
2428 } else if (pLockData) {
2429 /* lock structure can be returned on get */
2432 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2434 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2435 rc = -EIO; /* bad smb */
2438 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2439 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2440 if (data_count < sizeof(struct cifs_posix_lock)) {
2444 parm_data = (struct cifs_posix_lock *)
2445 ((char *)&pSMBr->hdr.Protocol + data_offset);
2446 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2447 pLockData->fl_type = F_UNLCK;
2449 if (parm_data->lock_type ==
2450 __constant_cpu_to_le16(CIFS_RDLCK))
2451 pLockData->fl_type = F_RDLCK;
2452 else if (parm_data->lock_type ==
2453 __constant_cpu_to_le16(CIFS_WRLCK))
2454 pLockData->fl_type = F_WRLCK;
2456 pLockData->fl_start = le64_to_cpu(parm_data->start);
2457 pLockData->fl_end = pLockData->fl_start +
2458 le64_to_cpu(parm_data->length) - 1;
2459 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2465 cifs_small_buf_release(pSMB);
2467 if (resp_buf_type == CIFS_SMALL_BUFFER)
2468 cifs_small_buf_release(iov[0].iov_base);
2469 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2470 cifs_buf_release(iov[0].iov_base);
2472 /* Note: On -EAGAIN error only caller can retry on handle based calls
2473 since file handle passed in no longer valid */
2480 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2483 CLOSE_REQ *pSMB = NULL;
2484 cFYI(1, "In CIFSSMBClose");
2486 /* do not retry on dead session on close */
2487 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2493 pSMB->FileID = (__u16) smb_file_id;
2494 pSMB->LastWriteTime = 0xFFFFFFFF;
2495 pSMB->ByteCount = 0;
2496 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2497 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2500 /* EINTR is expected when user ctl-c to kill app */
2501 cERROR(1, "Send error in Close = %d", rc);
2505 /* Since session is dead, file will be closed on server already */
2513 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2516 FLUSH_REQ *pSMB = NULL;
2517 cFYI(1, "In CIFSSMBFlush");
2519 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2523 pSMB->FileID = (__u16) smb_file_id;
2524 pSMB->ByteCount = 0;
2525 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2526 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2528 cERROR(1, "Send error in Flush = %d", rc);
2534 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2535 const char *from_name, const char *to_name,
2536 struct cifs_sb_info *cifs_sb)
2539 RENAME_REQ *pSMB = NULL;
2540 RENAME_RSP *pSMBr = NULL;
2542 int name_len, name_len2;
2544 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2546 cFYI(1, "In CIFSSMBRename");
2548 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2553 pSMB->BufferFormat = 0x04;
2554 pSMB->SearchAttributes =
2555 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2558 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2559 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2560 from_name, PATH_MAX,
2561 cifs_sb->local_nls, remap);
2562 name_len++; /* trailing null */
2564 pSMB->OldFileName[name_len] = 0x04; /* pad */
2565 /* protocol requires ASCII signature byte on Unicode string */
2566 pSMB->OldFileName[name_len + 1] = 0x00;
2568 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2569 to_name, PATH_MAX, cifs_sb->local_nls,
2571 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2572 name_len2 *= 2; /* convert to bytes */
2573 } else { /* BB improve the check for buffer overruns BB */
2574 name_len = strnlen(from_name, PATH_MAX);
2575 name_len++; /* trailing null */
2576 strncpy(pSMB->OldFileName, from_name, name_len);
2577 name_len2 = strnlen(to_name, PATH_MAX);
2578 name_len2++; /* trailing null */
2579 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2580 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2581 name_len2++; /* trailing null */
2582 name_len2++; /* signature byte */
2585 count = 1 /* 1st signature byte */ + name_len + name_len2;
2586 inc_rfc1001_len(pSMB, count);
2587 pSMB->ByteCount = cpu_to_le16(count);
2589 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2590 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2591 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2593 cFYI(1, "Send error in rename = %d", rc);
2595 cifs_buf_release(pSMB);
2603 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2604 int netfid, const char *target_name,
2605 const struct nls_table *nls_codepage, int remap)
2607 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2608 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2609 struct set_file_rename *rename_info;
2611 char dummy_string[30];
2613 int bytes_returned = 0;
2615 __u16 params, param_offset, offset, count, byte_count;
2617 cFYI(1, "Rename to File by handle");
2618 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2624 pSMB->MaxSetupCount = 0;
2628 pSMB->Reserved2 = 0;
2629 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2630 offset = param_offset + params;
2632 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2633 rename_info = (struct set_file_rename *) data_offset;
2634 pSMB->MaxParameterCount = cpu_to_le16(2);
2635 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2636 pSMB->SetupCount = 1;
2637 pSMB->Reserved3 = 0;
2638 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2639 byte_count = 3 /* pad */ + params;
2640 pSMB->ParameterCount = cpu_to_le16(params);
2641 pSMB->TotalParameterCount = pSMB->ParameterCount;
2642 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2643 pSMB->DataOffset = cpu_to_le16(offset);
2644 /* construct random name ".cifs_tmp<inodenum><mid>" */
2645 rename_info->overwrite = cpu_to_le32(1);
2646 rename_info->root_fid = 0;
2647 /* unicode only call */
2648 if (target_name == NULL) {
2649 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2651 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2652 dummy_string, 24, nls_codepage, remap);
2655 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2656 target_name, PATH_MAX, nls_codepage,
2659 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2660 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2661 byte_count += count;
2662 pSMB->DataCount = cpu_to_le16(count);
2663 pSMB->TotalDataCount = pSMB->DataCount;
2665 pSMB->InformationLevel =
2666 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2667 pSMB->Reserved4 = 0;
2668 inc_rfc1001_len(pSMB, byte_count);
2669 pSMB->ByteCount = cpu_to_le16(byte_count);
2670 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2671 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2672 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2674 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2676 cifs_buf_release(pSMB);
2678 /* Note: On -EAGAIN error only caller can retry on handle based calls
2679 since file handle passed in no longer valid */
2685 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2686 const char *fromName, const __u16 target_tid, const char *toName,
2687 const int flags, const struct nls_table *nls_codepage, int remap)
2690 COPY_REQ *pSMB = NULL;
2691 COPY_RSP *pSMBr = NULL;
2693 int name_len, name_len2;
2696 cFYI(1, "In CIFSSMBCopy");
2698 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2703 pSMB->BufferFormat = 0x04;
2704 pSMB->Tid2 = target_tid;
2706 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2708 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2709 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2710 fromName, PATH_MAX, nls_codepage,
2712 name_len++; /* trailing null */
2714 pSMB->OldFileName[name_len] = 0x04; /* pad */
2715 /* protocol requires ASCII signature byte on Unicode string */
2716 pSMB->OldFileName[name_len + 1] = 0x00;
2718 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2719 toName, PATH_MAX, nls_codepage, remap);
2720 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2721 name_len2 *= 2; /* convert to bytes */
2722 } else { /* BB improve the check for buffer overruns BB */
2723 name_len = strnlen(fromName, PATH_MAX);
2724 name_len++; /* trailing null */
2725 strncpy(pSMB->OldFileName, fromName, name_len);
2726 name_len2 = strnlen(toName, PATH_MAX);
2727 name_len2++; /* trailing null */
2728 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2729 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2730 name_len2++; /* trailing null */
2731 name_len2++; /* signature byte */
2734 count = 1 /* 1st signature byte */ + name_len + name_len2;
2735 inc_rfc1001_len(pSMB, count);
2736 pSMB->ByteCount = cpu_to_le16(count);
2738 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2739 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2741 cFYI(1, "Send error in copy = %d with %d files copied",
2742 rc, le16_to_cpu(pSMBr->CopyCount));
2744 cifs_buf_release(pSMB);
2753 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2754 const char *fromName, const char *toName,
2755 const struct nls_table *nls_codepage)
2757 TRANSACTION2_SPI_REQ *pSMB = NULL;
2758 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2761 int name_len_target;
2763 int bytes_returned = 0;
2764 __u16 params, param_offset, offset, byte_count;
2766 cFYI(1, "In Symlink Unix style");
2768 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2773 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2775 cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2776 /* find define for this maxpathcomponent */
2777 PATH_MAX, nls_codepage);
2778 name_len++; /* trailing null */
2781 } else { /* BB improve the check for buffer overruns BB */
2782 name_len = strnlen(fromName, PATH_MAX);
2783 name_len++; /* trailing null */
2784 strncpy(pSMB->FileName, fromName, name_len);
2786 params = 6 + name_len;
2787 pSMB->MaxSetupCount = 0;
2791 pSMB->Reserved2 = 0;
2792 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2793 InformationLevel) - 4;
2794 offset = param_offset + params;
2796 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2797 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2799 cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2800 /* find define for this maxpathcomponent */
2802 name_len_target++; /* trailing null */
2803 name_len_target *= 2;
2804 } else { /* BB improve the check for buffer overruns BB */
2805 name_len_target = strnlen(toName, PATH_MAX);
2806 name_len_target++; /* trailing null */
2807 strncpy(data_offset, toName, name_len_target);
2810 pSMB->MaxParameterCount = cpu_to_le16(2);
2811 /* BB find exact max on data count below from sess */
2812 pSMB->MaxDataCount = cpu_to_le16(1000);
2813 pSMB->SetupCount = 1;
2814 pSMB->Reserved3 = 0;
2815 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2816 byte_count = 3 /* pad */ + params + name_len_target;
2817 pSMB->DataCount = cpu_to_le16(name_len_target);
2818 pSMB->ParameterCount = cpu_to_le16(params);
2819 pSMB->TotalDataCount = pSMB->DataCount;
2820 pSMB->TotalParameterCount = pSMB->ParameterCount;
2821 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2822 pSMB->DataOffset = cpu_to_le16(offset);
2823 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2824 pSMB->Reserved4 = 0;
2825 inc_rfc1001_len(pSMB, byte_count);
2826 pSMB->ByteCount = cpu_to_le16(byte_count);
2827 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2828 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2829 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2831 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2833 cifs_buf_release(pSMB);
2836 goto createSymLinkRetry;
2842 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2843 const char *fromName, const char *toName,
2844 const struct nls_table *nls_codepage, int remap)
2846 TRANSACTION2_SPI_REQ *pSMB = NULL;
2847 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2850 int name_len_target;
2852 int bytes_returned = 0;
2853 __u16 params, param_offset, offset, byte_count;
2855 cFYI(1, "In Create Hard link Unix style");
2856 createHardLinkRetry:
2857 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2862 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2863 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2864 PATH_MAX, nls_codepage, remap);
2865 name_len++; /* trailing null */
2868 } else { /* BB improve the check for buffer overruns BB */
2869 name_len = strnlen(toName, PATH_MAX);
2870 name_len++; /* trailing null */
2871 strncpy(pSMB->FileName, toName, name_len);
2873 params = 6 + name_len;
2874 pSMB->MaxSetupCount = 0;
2878 pSMB->Reserved2 = 0;
2879 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2880 InformationLevel) - 4;
2881 offset = param_offset + params;
2883 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2884 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2886 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2887 PATH_MAX, nls_codepage, remap);
2888 name_len_target++; /* trailing null */
2889 name_len_target *= 2;
2890 } else { /* BB improve the check for buffer overruns BB */
2891 name_len_target = strnlen(fromName, PATH_MAX);
2892 name_len_target++; /* trailing null */
2893 strncpy(data_offset, fromName, name_len_target);
2896 pSMB->MaxParameterCount = cpu_to_le16(2);
2897 /* BB find exact max on data count below from sess*/
2898 pSMB->MaxDataCount = cpu_to_le16(1000);
2899 pSMB->SetupCount = 1;
2900 pSMB->Reserved3 = 0;
2901 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2902 byte_count = 3 /* pad */ + params + name_len_target;
2903 pSMB->ParameterCount = cpu_to_le16(params);
2904 pSMB->TotalParameterCount = pSMB->ParameterCount;
2905 pSMB->DataCount = cpu_to_le16(name_len_target);
2906 pSMB->TotalDataCount = pSMB->DataCount;
2907 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2908 pSMB->DataOffset = cpu_to_le16(offset);
2909 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2910 pSMB->Reserved4 = 0;
2911 inc_rfc1001_len(pSMB, byte_count);
2912 pSMB->ByteCount = cpu_to_le16(byte_count);
2913 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2914 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2915 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2917 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2919 cifs_buf_release(pSMB);
2921 goto createHardLinkRetry;
2927 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2928 const char *from_name, const char *to_name,
2929 struct cifs_sb_info *cifs_sb)
2932 NT_RENAME_REQ *pSMB = NULL;
2933 RENAME_RSP *pSMBr = NULL;
2935 int name_len, name_len2;
2937 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2939 cFYI(1, "In CIFSCreateHardLink");
2940 winCreateHardLinkRetry:
2942 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2947 pSMB->SearchAttributes =
2948 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2950 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2951 pSMB->ClusterCount = 0;
2953 pSMB->BufferFormat = 0x04;
2955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2957 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2958 PATH_MAX, cifs_sb->local_nls, remap);
2959 name_len++; /* trailing null */
2962 /* protocol specifies ASCII buffer format (0x04) for unicode */
2963 pSMB->OldFileName[name_len] = 0x04;
2964 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2966 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2967 to_name, PATH_MAX, cifs_sb->local_nls,
2969 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2970 name_len2 *= 2; /* convert to bytes */
2971 } else { /* BB improve the check for buffer overruns BB */
2972 name_len = strnlen(from_name, PATH_MAX);
2973 name_len++; /* trailing null */
2974 strncpy(pSMB->OldFileName, from_name, name_len);
2975 name_len2 = strnlen(to_name, PATH_MAX);
2976 name_len2++; /* trailing null */
2977 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2978 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2979 name_len2++; /* trailing null */
2980 name_len2++; /* signature byte */
2983 count = 1 /* string type byte */ + name_len + name_len2;
2984 inc_rfc1001_len(pSMB, count);
2985 pSMB->ByteCount = cpu_to_le16(count);
2987 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2988 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2989 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2991 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2993 cifs_buf_release(pSMB);
2995 goto winCreateHardLinkRetry;
3001 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3002 const unsigned char *searchName, char **symlinkinfo,
3003 const struct nls_table *nls_codepage)
3005 /* SMB_QUERY_FILE_UNIX_LINK */
3006 TRANSACTION2_QPI_REQ *pSMB = NULL;
3007 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3011 __u16 params, byte_count;
3014 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3017 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3022 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3024 cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3025 PATH_MAX, nls_codepage);
3026 name_len++; /* trailing null */
3028 } else { /* BB improve the check for buffer overruns BB */
3029 name_len = strnlen(searchName, PATH_MAX);
3030 name_len++; /* trailing null */
3031 strncpy(pSMB->FileName, searchName, name_len);
3034 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3035 pSMB->TotalDataCount = 0;
3036 pSMB->MaxParameterCount = cpu_to_le16(2);
3037 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3038 pSMB->MaxSetupCount = 0;
3042 pSMB->Reserved2 = 0;
3043 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3044 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3045 pSMB->DataCount = 0;
3046 pSMB->DataOffset = 0;
3047 pSMB->SetupCount = 1;
3048 pSMB->Reserved3 = 0;
3049 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3050 byte_count = params + 1 /* pad */ ;
3051 pSMB->TotalParameterCount = cpu_to_le16(params);
3052 pSMB->ParameterCount = pSMB->TotalParameterCount;
3053 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3054 pSMB->Reserved4 = 0;
3055 inc_rfc1001_len(pSMB, byte_count);
3056 pSMB->ByteCount = cpu_to_le16(byte_count);
3058 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3059 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3061 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3063 /* decode response */
3065 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3066 /* BB also check enough total bytes returned */
3067 if (rc || get_bcc(&pSMBr->hdr) < 2)
3071 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3073 data_start = ((char *) &pSMBr->hdr.Protocol) +
3074 le16_to_cpu(pSMBr->t2.DataOffset);
3076 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3081 /* BB FIXME investigate remapping reserved chars here */
3082 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3083 count, is_unicode, nls_codepage);
3088 cifs_buf_release(pSMB);
3090 goto querySymLinkRetry;
3094 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3096 * Recent Windows versions now create symlinks more frequently
3097 * and they use the "reparse point" mechanism below. We can of course
3098 * do symlinks nicely to Samba and other servers which support the
3099 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3100 * "MF" symlinks optionally, but for recent Windows we really need to
3101 * reenable the code below and fix the cifs_symlink callers to handle this.
3102 * In the interim this code has been moved to its own config option so
3103 * it is not compiled in by default until callers fixed up and more tested.
3106 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3107 const unsigned char *searchName,
3108 char *symlinkinfo, const int buflen, __u16 fid,
3109 const struct nls_table *nls_codepage)
3113 struct smb_com_transaction_ioctl_req *pSMB;
3114 struct smb_com_transaction_ioctl_rsp *pSMBr;
3116 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3117 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3122 pSMB->TotalParameterCount = 0 ;
3123 pSMB->TotalDataCount = 0;
3124 pSMB->MaxParameterCount = cpu_to_le32(2);
3125 /* BB find exact data count max from sess structure BB */
3126 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3127 pSMB->MaxSetupCount = 4;
3129 pSMB->ParameterOffset = 0;
3130 pSMB->DataCount = 0;
3131 pSMB->DataOffset = 0;
3132 pSMB->SetupCount = 4;
3133 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3134 pSMB->ParameterCount = pSMB->TotalParameterCount;
3135 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3136 pSMB->IsFsctl = 1; /* FSCTL */
3137 pSMB->IsRootFlag = 0;
3138 pSMB->Fid = fid; /* file handle always le */
3139 pSMB->ByteCount = 0;
3141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3144 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3145 } else { /* decode response */
3146 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3147 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3148 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3149 /* BB also check enough total bytes returned */
3150 rc = -EIO; /* bad smb */
3153 if (data_count && (data_count < 2048)) {
3154 char *end_of_smb = 2 /* sizeof byte count */ +
3155 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3157 struct reparse_data *reparse_buf =
3158 (struct reparse_data *)
3159 ((char *)&pSMBr->hdr.Protocol
3161 if ((char *)reparse_buf >= end_of_smb) {
3165 if ((reparse_buf->LinkNamesBuf +
3166 reparse_buf->TargetNameOffset +
3167 reparse_buf->TargetNameLen) > end_of_smb) {
3168 cFYI(1, "reparse buf beyond SMB");
3173 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3174 cifs_from_ucs2(symlinkinfo, (__le16 *)
3175 (reparse_buf->LinkNamesBuf +
3176 reparse_buf->TargetNameOffset),
3178 reparse_buf->TargetNameLen,
3180 } else { /* ASCII names */
3181 strncpy(symlinkinfo,
3182 reparse_buf->LinkNamesBuf +
3183 reparse_buf->TargetNameOffset,
3184 min_t(const int, buflen,
3185 reparse_buf->TargetNameLen));
3189 cFYI(1, "Invalid return data count on "
3190 "get reparse info ioctl");
3192 symlinkinfo[buflen] = 0; /* just in case so the caller
3193 does not go off the end of the buffer */
3194 cFYI(1, "readlink result - %s", symlinkinfo);
3198 cifs_buf_release(pSMB);
3200 /* Note: On -EAGAIN error only caller can retry on handle based calls
3201 since file handle passed in no longer valid */
3205 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3207 #ifdef CONFIG_CIFS_POSIX
3209 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3210 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3211 struct cifs_posix_ace *cifs_ace)
3213 /* u8 cifs fields do not need le conversion */
3214 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3215 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3216 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3217 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3222 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3223 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3224 const int acl_type, const int size_of_data_area)
3229 struct cifs_posix_ace *pACE;
3230 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3231 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3233 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3236 if (acl_type & ACL_TYPE_ACCESS) {
3237 count = le16_to_cpu(cifs_acl->access_entry_count);
3238 pACE = &cifs_acl->ace_array[0];
3239 size = sizeof(struct cifs_posix_acl);
3240 size += sizeof(struct cifs_posix_ace) * count;
3241 /* check if we would go beyond end of SMB */
3242 if (size_of_data_area < size) {
3243 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3244 size_of_data_area, size);
3247 } else if (acl_type & ACL_TYPE_DEFAULT) {
3248 count = le16_to_cpu(cifs_acl->access_entry_count);
3249 size = sizeof(struct cifs_posix_acl);
3250 size += sizeof(struct cifs_posix_ace) * count;
3251 /* skip past access ACEs to get to default ACEs */
3252 pACE = &cifs_acl->ace_array[count];
3253 count = le16_to_cpu(cifs_acl->default_entry_count);
3254 size += sizeof(struct cifs_posix_ace) * count;
3255 /* check if we would go beyond end of SMB */
3256 if (size_of_data_area < size)
3263 size = posix_acl_xattr_size(count);
3264 if ((buflen == 0) || (local_acl == NULL)) {
3265 /* used to query ACL EA size */
3266 } else if (size > buflen) {
3268 } else /* buffer big enough */ {
3269 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3270 for (i = 0; i < count ; i++) {
3271 cifs_convert_ace(&local_acl->a_entries[i], pACE);
3278 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3279 const posix_acl_xattr_entry *local_ace)
3281 __u16 rc = 0; /* 0 = ACL converted ok */
3283 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3284 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3285 /* BB is there a better way to handle the large uid? */
3286 if (local_ace->e_id == cpu_to_le32(-1)) {
3287 /* Probably no need to le convert -1 on any arch but can not hurt */
3288 cifs_ace->cifs_uid = cpu_to_le64(-1);
3290 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3291 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3295 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3296 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3297 const int buflen, const int acl_type)
3300 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3301 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3305 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3308 count = posix_acl_xattr_count((size_t)buflen);
3309 cFYI(1, "setting acl with %d entries from buf of length %d and "
3311 count, buflen, le32_to_cpu(local_acl->a_version));
3312 if (le32_to_cpu(local_acl->a_version) != 2) {
3313 cFYI(1, "unknown POSIX ACL version %d",
3314 le32_to_cpu(local_acl->a_version));
3317 cifs_acl->version = cpu_to_le16(1);
3318 if (acl_type == ACL_TYPE_ACCESS)
3319 cifs_acl->access_entry_count = cpu_to_le16(count);
3320 else if (acl_type == ACL_TYPE_DEFAULT)
3321 cifs_acl->default_entry_count = cpu_to_le16(count);
3323 cFYI(1, "unknown ACL type %d", acl_type);
3326 for (i = 0; i < count; i++) {
3327 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3328 &local_acl->a_entries[i]);
3330 /* ACE not converted */
3335 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3336 rc += sizeof(struct cifs_posix_acl);
3337 /* BB add check to make sure ACL does not overflow SMB */
3343 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3344 const unsigned char *searchName,
3345 char *acl_inf, const int buflen, const int acl_type,
3346 const struct nls_table *nls_codepage, int remap)
3348 /* SMB_QUERY_POSIX_ACL */
3349 TRANSACTION2_QPI_REQ *pSMB = NULL;
3350 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3354 __u16 params, byte_count;
3356 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3359 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3364 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3366 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3367 searchName, PATH_MAX, nls_codepage,
3369 name_len++; /* trailing null */
3371 pSMB->FileName[name_len] = 0;
3372 pSMB->FileName[name_len+1] = 0;
3373 } else { /* BB improve the check for buffer overruns BB */
3374 name_len = strnlen(searchName, PATH_MAX);
3375 name_len++; /* trailing null */
3376 strncpy(pSMB->FileName, searchName, name_len);
3379 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3380 pSMB->TotalDataCount = 0;
3381 pSMB->MaxParameterCount = cpu_to_le16(2);
3382 /* BB find exact max data count below from sess structure BB */
3383 pSMB->MaxDataCount = cpu_to_le16(4000);
3384 pSMB->MaxSetupCount = 0;
3388 pSMB->Reserved2 = 0;
3389 pSMB->ParameterOffset = cpu_to_le16(
3390 offsetof(struct smb_com_transaction2_qpi_req,
3391 InformationLevel) - 4);
3392 pSMB->DataCount = 0;
3393 pSMB->DataOffset = 0;
3394 pSMB->SetupCount = 1;
3395 pSMB->Reserved3 = 0;
3396 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3397 byte_count = params + 1 /* pad */ ;
3398 pSMB->TotalParameterCount = cpu_to_le16(params);
3399 pSMB->ParameterCount = pSMB->TotalParameterCount;
3400 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3401 pSMB->Reserved4 = 0;
3402 inc_rfc1001_len(pSMB, byte_count);
3403 pSMB->ByteCount = cpu_to_le16(byte_count);
3405 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3406 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3407 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3409 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3411 /* decode response */
3413 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3414 /* BB also check enough total bytes returned */
3415 if (rc || get_bcc(&pSMBr->hdr) < 2)
3416 rc = -EIO; /* bad smb */
3418 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3419 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3420 rc = cifs_copy_posix_acl(acl_inf,
3421 (char *)&pSMBr->hdr.Protocol+data_offset,
3422 buflen, acl_type, count);
3425 cifs_buf_release(pSMB);
3432 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3433 const unsigned char *fileName,
3434 const char *local_acl, const int buflen,
3436 const struct nls_table *nls_codepage, int remap)
3438 struct smb_com_transaction2_spi_req *pSMB = NULL;
3439 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3443 int bytes_returned = 0;
3444 __u16 params, byte_count, data_count, param_offset, offset;
3446 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3448 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3452 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3454 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3455 PATH_MAX, nls_codepage, remap);
3456 name_len++; /* trailing null */
3458 } else { /* BB improve the check for buffer overruns BB */
3459 name_len = strnlen(fileName, PATH_MAX);
3460 name_len++; /* trailing null */
3461 strncpy(pSMB->FileName, fileName, name_len);
3463 params = 6 + name_len;
3464 pSMB->MaxParameterCount = cpu_to_le16(2);
3465 /* BB find max SMB size from sess */
3466 pSMB->MaxDataCount = cpu_to_le16(1000);
3467 pSMB->MaxSetupCount = 0;
3471 pSMB->Reserved2 = 0;
3472 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3473 InformationLevel) - 4;
3474 offset = param_offset + params;
3475 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3476 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3478 /* convert to on the wire format for POSIX ACL */
3479 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3481 if (data_count == 0) {
3483 goto setACLerrorExit;
3485 pSMB->DataOffset = cpu_to_le16(offset);
3486 pSMB->SetupCount = 1;
3487 pSMB->Reserved3 = 0;
3488 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3489 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3490 byte_count = 3 /* pad */ + params + data_count;
3491 pSMB->DataCount = cpu_to_le16(data_count);
3492 pSMB->TotalDataCount = pSMB->DataCount;
3493 pSMB->ParameterCount = cpu_to_le16(params);
3494 pSMB->TotalParameterCount = pSMB->ParameterCount;
3495 pSMB->Reserved4 = 0;
3496 inc_rfc1001_len(pSMB, byte_count);
3497 pSMB->ByteCount = cpu_to_le16(byte_count);
3498 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3499 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3501 cFYI(1, "Set POSIX ACL returned %d", rc);
3504 cifs_buf_release(pSMB);
3510 /* BB fix tabs in this function FIXME BB */
3512 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3513 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3516 struct smb_t2_qfi_req *pSMB = NULL;
3517 struct smb_t2_qfi_rsp *pSMBr = NULL;
3519 __u16 params, byte_count;
3521 cFYI(1, "In GetExtAttr");
3526 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3531 params = 2 /* level */ + 2 /* fid */;
3532 pSMB->t2.TotalDataCount = 0;
3533 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3534 /* BB find exact max data count below from sess structure BB */
3535 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3536 pSMB->t2.MaxSetupCount = 0;
3537 pSMB->t2.Reserved = 0;
3539 pSMB->t2.Timeout = 0;
3540 pSMB->t2.Reserved2 = 0;
3541 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3543 pSMB->t2.DataCount = 0;
3544 pSMB->t2.DataOffset = 0;
3545 pSMB->t2.SetupCount = 1;
3546 pSMB->t2.Reserved3 = 0;
3547 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3548 byte_count = params + 1 /* pad */ ;
3549 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3550 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3551 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3554 inc_rfc1001_len(pSMB, byte_count);
3555 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3557 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3558 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3560 cFYI(1, "error %d in GetExtAttr", rc);
3562 /* decode response */
3563 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3564 /* BB also check enough total bytes returned */
3565 if (rc || get_bcc(&pSMBr->hdr) < 2)
3566 /* If rc should we check for EOPNOSUPP and
3567 disable the srvino flag? or in caller? */
3568 rc = -EIO; /* bad smb */
3570 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3571 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3572 struct file_chattr_info *pfinfo;
3573 /* BB Do we need a cast or hash here ? */
3575 cFYI(1, "Illegal size ret in GetExtAttr");
3579 pfinfo = (struct file_chattr_info *)
3580 (data_offset + (char *) &pSMBr->hdr.Protocol);
3581 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3582 *pMask = le64_to_cpu(pfinfo->mask);
3586 cifs_buf_release(pSMB);
3588 goto GetExtAttrRetry;
3592 #endif /* CONFIG_POSIX */
3594 #ifdef CONFIG_CIFS_ACL
3596 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3597 * all NT TRANSACTS that we init here have total parm and data under about 400
3598 * bytes (to fit in small cifs buffer size), which is the case so far, it
3599 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3600 * returned setup area) and MaxParameterCount (returned parms size) must be set
3604 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3605 const int parm_len, struct cifs_tcon *tcon,
3610 struct smb_com_ntransact_req *pSMB;
3612 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3616 *ret_buf = (void *)pSMB;
3618 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3619 pSMB->TotalDataCount = 0;
3620 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3621 pSMB->ParameterCount = pSMB->TotalParameterCount;
3622 pSMB->DataCount = pSMB->TotalDataCount;
3623 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3624 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3625 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3626 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3627 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3628 pSMB->SubCommand = cpu_to_le16(sub_command);
3633 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3634 __u32 *pparmlen, __u32 *pdatalen)
3637 __u32 data_count, data_offset, parm_count, parm_offset;
3638 struct smb_com_ntransact_rsp *pSMBr;
3647 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3649 bcc = get_bcc(&pSMBr->hdr);
3650 end_of_smb = 2 /* sizeof byte count */ + bcc +
3651 (char *)&pSMBr->ByteCount;
3653 data_offset = le32_to_cpu(pSMBr->DataOffset);
3654 data_count = le32_to_cpu(pSMBr->DataCount);
3655 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3656 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3658 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3659 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3661 /* should we also check that parm and data areas do not overlap? */
3662 if (*ppparm > end_of_smb) {
3663 cFYI(1, "parms start after end of smb");
3665 } else if (parm_count + *ppparm > end_of_smb) {
3666 cFYI(1, "parm end after end of smb");
3668 } else if (*ppdata > end_of_smb) {
3669 cFYI(1, "data starts after end of smb");
3671 } else if (data_count + *ppdata > end_of_smb) {
3672 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3673 *ppdata, data_count, (data_count + *ppdata),
3676 } else if (parm_count + data_count > bcc) {
3677 cFYI(1, "parm count and data count larger than SMB");
3680 *pdatalen = data_count;
3681 *pparmlen = parm_count;
3685 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3687 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3688 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3692 QUERY_SEC_DESC_REQ *pSMB;
3695 cFYI(1, "GetCifsACL");
3700 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3701 8 /* parm len */, tcon, (void **) &pSMB);
3705 pSMB->MaxParameterCount = cpu_to_le32(4);
3706 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3707 pSMB->MaxSetupCount = 0;
3708 pSMB->Fid = fid; /* file handle always le */
3709 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3711 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3712 inc_rfc1001_len(pSMB, 11);
3713 iov[0].iov_base = (char *)pSMB;
3714 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3716 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3718 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3720 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3721 } else { /* decode response */
3725 struct smb_com_ntransact_rsp *pSMBr;
3728 /* validate_nttransact */
3729 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3730 &pdata, &parm_len, pbuflen);
3733 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3735 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3737 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3738 rc = -EIO; /* bad smb */
3743 /* BB check that data area is minimum length and as big as acl_len */
3745 acl_len = le32_to_cpu(*parm);
3746 if (acl_len != *pbuflen) {
3747 cERROR(1, "acl length %d does not match %d",
3749 if (*pbuflen > acl_len)
3753 /* check if buffer is big enough for the acl
3754 header followed by the smallest SID */
3755 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3756 (*pbuflen >= 64 * 1024)) {
3757 cERROR(1, "bad acl length %d", *pbuflen);
3761 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3762 if (*acl_inf == NULL) {
3766 memcpy(*acl_inf, pdata, *pbuflen);
3770 if (buf_type == CIFS_SMALL_BUFFER)
3771 cifs_small_buf_release(iov[0].iov_base);
3772 else if (buf_type == CIFS_LARGE_BUFFER)
3773 cifs_buf_release(iov[0].iov_base);
3774 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3779 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3780 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3782 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3784 int bytes_returned = 0;
3785 SET_SEC_DESC_REQ *pSMB = NULL;
3789 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3793 pSMB->MaxSetupCount = 0;
3797 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3798 data_count = acllen;
3799 data_offset = param_offset + param_count;
3800 byte_count = 3 /* pad */ + param_count;
3802 pSMB->DataCount = cpu_to_le32(data_count);
3803 pSMB->TotalDataCount = pSMB->DataCount;
3804 pSMB->MaxParameterCount = cpu_to_le32(4);
3805 pSMB->MaxDataCount = cpu_to_le32(16384);
3806 pSMB->ParameterCount = cpu_to_le32(param_count);
3807 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3808 pSMB->TotalParameterCount = pSMB->ParameterCount;
3809 pSMB->DataOffset = cpu_to_le32(data_offset);
3810 pSMB->SetupCount = 0;
3811 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3812 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3814 pSMB->Fid = fid; /* file handle always le */
3815 pSMB->Reserved2 = 0;
3816 pSMB->AclFlags = cpu_to_le32(aclflag);
3818 if (pntsd && acllen) {
3819 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3820 data_offset, pntsd, acllen);
3821 inc_rfc1001_len(pSMB, byte_count + data_count);
3823 inc_rfc1001_len(pSMB, byte_count);
3825 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3826 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3828 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3830 cFYI(1, "Set CIFS ACL returned %d", rc);
3831 cifs_buf_release(pSMB);
3834 goto setCifsAclRetry;
3839 #endif /* CONFIG_CIFS_ACL */
3841 /* Legacy Query Path Information call for lookup to old servers such
3844 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3845 const char *search_name, FILE_ALL_INFO *data,
3846 const struct nls_table *nls_codepage, int remap)
3848 QUERY_INFORMATION_REQ *pSMB;
3849 QUERY_INFORMATION_RSP *pSMBr;
3854 cFYI(1, "In SMBQPath path %s", search_name);
3856 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3861 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3863 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3864 search_name, PATH_MAX, nls_codepage,
3866 name_len++; /* trailing null */
3869 name_len = strnlen(search_name, PATH_MAX);
3870 name_len++; /* trailing null */
3871 strncpy(pSMB->FileName, search_name, name_len);
3873 pSMB->BufferFormat = 0x04;
3874 name_len++; /* account for buffer type byte */
3875 inc_rfc1001_len(pSMB, (__u16)name_len);
3876 pSMB->ByteCount = cpu_to_le16(name_len);
3878 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3879 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3881 cFYI(1, "Send error in QueryInfo = %d", rc);
3884 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3886 /* decode response */
3887 /* BB FIXME - add time zone adjustment BB */
3888 memset(data, 0, sizeof(FILE_ALL_INFO));
3891 /* decode time fields */
3892 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3893 data->LastWriteTime = data->ChangeTime;
3894 data->LastAccessTime = 0;
3895 data->AllocationSize =
3896 cpu_to_le64(le32_to_cpu(pSMBr->size));
3897 data->EndOfFile = data->AllocationSize;
3899 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3901 rc = -EIO; /* bad buffer passed in */
3903 cifs_buf_release(pSMB);
3912 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3913 u16 netfid, FILE_ALL_INFO *pFindData)
3915 struct smb_t2_qfi_req *pSMB = NULL;
3916 struct smb_t2_qfi_rsp *pSMBr = NULL;
3919 __u16 params, byte_count;
3922 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3927 params = 2 /* level */ + 2 /* fid */;
3928 pSMB->t2.TotalDataCount = 0;
3929 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3930 /* BB find exact max data count below from sess structure BB */
3931 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3932 pSMB->t2.MaxSetupCount = 0;
3933 pSMB->t2.Reserved = 0;
3935 pSMB->t2.Timeout = 0;
3936 pSMB->t2.Reserved2 = 0;
3937 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3939 pSMB->t2.DataCount = 0;
3940 pSMB->t2.DataOffset = 0;
3941 pSMB->t2.SetupCount = 1;
3942 pSMB->t2.Reserved3 = 0;
3943 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3944 byte_count = params + 1 /* pad */ ;
3945 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3946 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3947 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3950 inc_rfc1001_len(pSMB, byte_count);
3952 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3953 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3955 cFYI(1, "Send error in QPathInfo = %d", rc);
3956 } else { /* decode response */
3957 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3959 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3961 else if (get_bcc(&pSMBr->hdr) < 40)
3962 rc = -EIO; /* bad smb */
3963 else if (pFindData) {
3964 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3965 memcpy((char *) pFindData,
3966 (char *) &pSMBr->hdr.Protocol +
3967 data_offset, sizeof(FILE_ALL_INFO));
3971 cifs_buf_release(pSMB);
3973 goto QFileInfoRetry;
3979 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3980 const char *search_name, FILE_ALL_INFO *data,
3981 int legacy /* old style infolevel */,
3982 const struct nls_table *nls_codepage, int remap)
3984 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3985 TRANSACTION2_QPI_REQ *pSMB = NULL;
3986 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3990 __u16 params, byte_count;
3992 /* cFYI(1, "In QPathInfo path %s", search_name); */
3994 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3999 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4001 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4002 PATH_MAX, nls_codepage, remap);
4003 name_len++; /* trailing null */
4005 } else { /* BB improve the check for buffer overruns BB */
4006 name_len = strnlen(search_name, PATH_MAX);
4007 name_len++; /* trailing null */
4008 strncpy(pSMB->FileName, search_name, name_len);
4011 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4012 pSMB->TotalDataCount = 0;
4013 pSMB->MaxParameterCount = cpu_to_le16(2);
4014 /* BB find exact max SMB PDU from sess structure BB */
4015 pSMB->MaxDataCount = cpu_to_le16(4000);
4016 pSMB->MaxSetupCount = 0;
4020 pSMB->Reserved2 = 0;
4021 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4022 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4023 pSMB->DataCount = 0;
4024 pSMB->DataOffset = 0;
4025 pSMB->SetupCount = 1;
4026 pSMB->Reserved3 = 0;
4027 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4028 byte_count = params + 1 /* pad */ ;
4029 pSMB->TotalParameterCount = cpu_to_le16(params);
4030 pSMB->ParameterCount = pSMB->TotalParameterCount;
4032 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4034 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4035 pSMB->Reserved4 = 0;
4036 inc_rfc1001_len(pSMB, byte_count);
4037 pSMB->ByteCount = cpu_to_le16(byte_count);
4039 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4040 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4042 cFYI(1, "Send error in QPathInfo = %d", rc);
4043 } else { /* decode response */
4044 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4046 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4048 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4049 rc = -EIO; /* bad smb */
4050 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4051 rc = -EIO; /* 24 or 26 expected but we do not read
4055 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4058 * On legacy responses we do not read the last field,
4059 * EAsize, fortunately since it varies by subdialect and
4060 * also note it differs on Set vs Get, ie two bytes or 4
4061 * bytes depending but we don't care here.
4064 size = sizeof(FILE_INFO_STANDARD);
4066 size = sizeof(FILE_ALL_INFO);
4067 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4072 cifs_buf_release(pSMB);
4074 goto QPathInfoRetry;
4080 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4081 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4083 struct smb_t2_qfi_req *pSMB = NULL;
4084 struct smb_t2_qfi_rsp *pSMBr = NULL;
4087 __u16 params, byte_count;
4090 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4095 params = 2 /* level */ + 2 /* fid */;
4096 pSMB->t2.TotalDataCount = 0;
4097 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4098 /* BB find exact max data count below from sess structure BB */
4099 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4100 pSMB->t2.MaxSetupCount = 0;
4101 pSMB->t2.Reserved = 0;
4103 pSMB->t2.Timeout = 0;
4104 pSMB->t2.Reserved2 = 0;
4105 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4107 pSMB->t2.DataCount = 0;
4108 pSMB->t2.DataOffset = 0;
4109 pSMB->t2.SetupCount = 1;
4110 pSMB->t2.Reserved3 = 0;
4111 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4112 byte_count = params + 1 /* pad */ ;
4113 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4114 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4115 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4118 inc_rfc1001_len(pSMB, byte_count);
4120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4123 cFYI(1, "Send error in QPathInfo = %d", rc);
4124 } else { /* decode response */
4125 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4127 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4128 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4129 "Unix Extensions can be disabled on mount "
4130 "by specifying the nosfu mount option.");
4131 rc = -EIO; /* bad smb */
4133 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4134 memcpy((char *) pFindData,
4135 (char *) &pSMBr->hdr.Protocol +
4137 sizeof(FILE_UNIX_BASIC_INFO));
4141 cifs_buf_release(pSMB);
4143 goto UnixQFileInfoRetry;
4149 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4150 const unsigned char *searchName,
4151 FILE_UNIX_BASIC_INFO *pFindData,
4152 const struct nls_table *nls_codepage, int remap)
4154 /* SMB_QUERY_FILE_UNIX_BASIC */
4155 TRANSACTION2_QPI_REQ *pSMB = NULL;
4156 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4158 int bytes_returned = 0;
4160 __u16 params, byte_count;
4162 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4164 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4169 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4171 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4172 PATH_MAX, nls_codepage, remap);
4173 name_len++; /* trailing null */
4175 } else { /* BB improve the check for buffer overruns BB */
4176 name_len = strnlen(searchName, PATH_MAX);
4177 name_len++; /* trailing null */
4178 strncpy(pSMB->FileName, searchName, name_len);
4181 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4182 pSMB->TotalDataCount = 0;
4183 pSMB->MaxParameterCount = cpu_to_le16(2);
4184 /* BB find exact max SMB PDU from sess structure BB */
4185 pSMB->MaxDataCount = cpu_to_le16(4000);
4186 pSMB->MaxSetupCount = 0;
4190 pSMB->Reserved2 = 0;
4191 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4192 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4193 pSMB->DataCount = 0;
4194 pSMB->DataOffset = 0;
4195 pSMB->SetupCount = 1;
4196 pSMB->Reserved3 = 0;
4197 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4198 byte_count = params + 1 /* pad */ ;
4199 pSMB->TotalParameterCount = cpu_to_le16(params);
4200 pSMB->ParameterCount = pSMB->TotalParameterCount;
4201 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4202 pSMB->Reserved4 = 0;
4203 inc_rfc1001_len(pSMB, byte_count);
4204 pSMB->ByteCount = cpu_to_le16(byte_count);
4206 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4207 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4209 cFYI(1, "Send error in QPathInfo = %d", rc);
4210 } else { /* decode response */
4211 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4213 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4214 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4215 "Unix Extensions can be disabled on mount "
4216 "by specifying the nosfu mount option.");
4217 rc = -EIO; /* bad smb */
4219 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4220 memcpy((char *) pFindData,
4221 (char *) &pSMBr->hdr.Protocol +
4223 sizeof(FILE_UNIX_BASIC_INFO));
4226 cifs_buf_release(pSMB);
4228 goto UnixQPathInfoRetry;
4233 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4235 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4236 const char *searchName,
4237 const struct nls_table *nls_codepage,
4238 __u16 *pnetfid, __u16 search_flags,
4239 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4241 /* level 257 SMB_ */
4242 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4243 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4244 T2_FFIRST_RSP_PARMS *parms;
4246 int bytes_returned = 0;
4248 __u16 params, byte_count;
4250 cFYI(1, "In FindFirst for %s", searchName);
4253 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4258 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4260 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4261 PATH_MAX, nls_codepage, remap);
4262 /* We can not add the asterik earlier in case
4263 it got remapped to 0xF03A as if it were part of the
4264 directory name instead of a wildcard */
4266 pSMB->FileName[name_len] = dirsep;
4267 pSMB->FileName[name_len+1] = 0;
4268 pSMB->FileName[name_len+2] = '*';
4269 pSMB->FileName[name_len+3] = 0;
4270 name_len += 4; /* now the trailing null */
4271 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4272 pSMB->FileName[name_len+1] = 0;
4274 } else { /* BB add check for overrun of SMB buf BB */
4275 name_len = strnlen(searchName, PATH_MAX);
4276 /* BB fix here and in unicode clause above ie
4277 if (name_len > buffersize-header)
4278 free buffer exit; BB */
4279 strncpy(pSMB->FileName, searchName, name_len);
4280 pSMB->FileName[name_len] = dirsep;
4281 pSMB->FileName[name_len+1] = '*';
4282 pSMB->FileName[name_len+2] = 0;
4286 params = 12 + name_len /* includes null */ ;
4287 pSMB->TotalDataCount = 0; /* no EAs */
4288 pSMB->MaxParameterCount = cpu_to_le16(10);
4289 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4290 pSMB->MaxSetupCount = 0;
4294 pSMB->Reserved2 = 0;
4295 byte_count = params + 1 /* pad */ ;
4296 pSMB->TotalParameterCount = cpu_to_le16(params);
4297 pSMB->ParameterCount = pSMB->TotalParameterCount;
4298 pSMB->ParameterOffset = cpu_to_le16(
4299 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4301 pSMB->DataCount = 0;
4302 pSMB->DataOffset = 0;
4303 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4304 pSMB->Reserved3 = 0;
4305 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4306 pSMB->SearchAttributes =
4307 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4309 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4310 pSMB->SearchFlags = cpu_to_le16(search_flags);
4311 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4313 /* BB what should we set StorageType to? Does it matter? BB */
4314 pSMB->SearchStorageType = 0;
4315 inc_rfc1001_len(pSMB, byte_count);
4316 pSMB->ByteCount = cpu_to_le16(byte_count);
4318 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4319 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4320 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4322 if (rc) {/* BB add logic to retry regular search if Unix search
4323 rejected unexpectedly by server */
4324 /* BB Add code to handle unsupported level rc */
4325 cFYI(1, "Error in FindFirst = %d", rc);
4327 cifs_buf_release(pSMB);
4329 /* BB eventually could optimize out free and realloc of buf */
4332 goto findFirstRetry;
4333 } else { /* decode response */
4334 /* BB remember to free buffer if error BB */
4335 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4339 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4340 psrch_inf->unicode = true;
4342 psrch_inf->unicode = false;
4344 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4345 psrch_inf->smallBuf = 0;
4346 psrch_inf->srch_entries_start =
4347 (char *) &pSMBr->hdr.Protocol +
4348 le16_to_cpu(pSMBr->t2.DataOffset);
4349 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4350 le16_to_cpu(pSMBr->t2.ParameterOffset));
4352 if (parms->EndofSearch)
4353 psrch_inf->endOfSearch = true;
4355 psrch_inf->endOfSearch = false;
4357 psrch_inf->entries_in_buffer =
4358 le16_to_cpu(parms->SearchCount);
4359 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4360 psrch_inf->entries_in_buffer;
4361 lnoff = le16_to_cpu(parms->LastNameOffset);
4362 if (CIFSMaxBufSize < lnoff) {
4363 cERROR(1, "ignoring corrupt resume name");
4364 psrch_inf->last_entry = NULL;
4368 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4371 *pnetfid = parms->SearchHandle;
4373 cifs_buf_release(pSMB);
4380 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4381 __u16 searchHandle, __u16 search_flags,
4382 struct cifs_search_info *psrch_inf)
4384 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4385 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4386 T2_FNEXT_RSP_PARMS *parms;
4387 char *response_data;
4390 unsigned int name_len;
4391 __u16 params, byte_count;
4393 cFYI(1, "In FindNext");
4395 if (psrch_inf->endOfSearch)
4398 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4403 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4405 pSMB->TotalDataCount = 0; /* no EAs */
4406 pSMB->MaxParameterCount = cpu_to_le16(8);
4407 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4408 pSMB->MaxSetupCount = 0;
4412 pSMB->Reserved2 = 0;
4413 pSMB->ParameterOffset = cpu_to_le16(
4414 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4415 pSMB->DataCount = 0;
4416 pSMB->DataOffset = 0;
4417 pSMB->SetupCount = 1;
4418 pSMB->Reserved3 = 0;
4419 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4420 pSMB->SearchHandle = searchHandle; /* always kept as le */
4422 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4423 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4424 pSMB->ResumeKey = psrch_inf->resume_key;
4425 pSMB->SearchFlags = cpu_to_le16(search_flags);
4427 name_len = psrch_inf->resume_name_len;
4429 if (name_len < PATH_MAX) {
4430 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4431 byte_count += name_len;
4432 /* 14 byte parm len above enough for 2 byte null terminator */
4433 pSMB->ResumeFileName[name_len] = 0;
4434 pSMB->ResumeFileName[name_len+1] = 0;
4437 goto FNext2_err_exit;
4439 byte_count = params + 1 /* pad */ ;
4440 pSMB->TotalParameterCount = cpu_to_le16(params);
4441 pSMB->ParameterCount = pSMB->TotalParameterCount;
4442 inc_rfc1001_len(pSMB, byte_count);
4443 pSMB->ByteCount = cpu_to_le16(byte_count);
4445 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4446 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4447 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4450 psrch_inf->endOfSearch = true;
4451 cifs_buf_release(pSMB);
4452 rc = 0; /* search probably was closed at end of search*/
4454 cFYI(1, "FindNext returned = %d", rc);
4455 } else { /* decode response */
4456 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4461 /* BB fixme add lock for file (srch_info) struct here */
4462 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4463 psrch_inf->unicode = true;
4465 psrch_inf->unicode = false;
4466 response_data = (char *) &pSMBr->hdr.Protocol +
4467 le16_to_cpu(pSMBr->t2.ParameterOffset);
4468 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4469 response_data = (char *)&pSMBr->hdr.Protocol +
4470 le16_to_cpu(pSMBr->t2.DataOffset);
4471 if (psrch_inf->smallBuf)
4472 cifs_small_buf_release(
4473 psrch_inf->ntwrk_buf_start);
4475 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4476 psrch_inf->srch_entries_start = response_data;
4477 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4478 psrch_inf->smallBuf = 0;
4479 if (parms->EndofSearch)
4480 psrch_inf->endOfSearch = true;
4482 psrch_inf->endOfSearch = false;
4483 psrch_inf->entries_in_buffer =
4484 le16_to_cpu(parms->SearchCount);
4485 psrch_inf->index_of_last_entry +=
4486 psrch_inf->entries_in_buffer;
4487 lnoff = le16_to_cpu(parms->LastNameOffset);
4488 if (CIFSMaxBufSize < lnoff) {
4489 cERROR(1, "ignoring corrupt resume name");
4490 psrch_inf->last_entry = NULL;
4493 psrch_inf->last_entry =
4494 psrch_inf->srch_entries_start + lnoff;
4496 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4497 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4499 /* BB fixme add unlock here */
4504 /* BB On error, should we leave previous search buf (and count and
4505 last entry fields) intact or free the previous one? */
4507 /* Note: On -EAGAIN error only caller can retry on handle based calls
4508 since file handle passed in no longer valid */
4511 cifs_buf_release(pSMB);
4516 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4517 const __u16 searchHandle)
4520 FINDCLOSE_REQ *pSMB = NULL;
4522 cFYI(1, "In CIFSSMBFindClose");
4523 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4525 /* no sense returning error if session restarted
4526 as file handle has been closed */
4532 pSMB->FileID = searchHandle;
4533 pSMB->ByteCount = 0;
4534 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4536 cERROR(1, "Send error in FindClose = %d", rc);
4538 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4540 /* Since session is dead, search handle closed on server already */
4548 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4549 const char *search_name, __u64 *inode_number,
4550 const struct nls_table *nls_codepage, int remap)
4553 TRANSACTION2_QPI_REQ *pSMB = NULL;
4554 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4555 int name_len, bytes_returned;
4556 __u16 params, byte_count;
4558 cFYI(1, "In GetSrvInodeNum for %s", search_name);
4562 GetInodeNumberRetry:
4563 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4568 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4570 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4571 search_name, PATH_MAX, nls_codepage,
4573 name_len++; /* trailing null */
4575 } else { /* BB improve the check for buffer overruns BB */
4576 name_len = strnlen(search_name, PATH_MAX);
4577 name_len++; /* trailing null */
4578 strncpy(pSMB->FileName, search_name, name_len);
4581 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4582 pSMB->TotalDataCount = 0;
4583 pSMB->MaxParameterCount = cpu_to_le16(2);
4584 /* BB find exact max data count below from sess structure BB */
4585 pSMB->MaxDataCount = cpu_to_le16(4000);
4586 pSMB->MaxSetupCount = 0;
4590 pSMB->Reserved2 = 0;
4591 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4592 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4593 pSMB->DataCount = 0;
4594 pSMB->DataOffset = 0;
4595 pSMB->SetupCount = 1;
4596 pSMB->Reserved3 = 0;
4597 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4598 byte_count = params + 1 /* pad */ ;
4599 pSMB->TotalParameterCount = cpu_to_le16(params);
4600 pSMB->ParameterCount = pSMB->TotalParameterCount;
4601 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4602 pSMB->Reserved4 = 0;
4603 inc_rfc1001_len(pSMB, byte_count);
4604 pSMB->ByteCount = cpu_to_le16(byte_count);
4606 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4607 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4609 cFYI(1, "error %d in QueryInternalInfo", rc);
4611 /* decode response */
4612 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4613 /* BB also check enough total bytes returned */
4614 if (rc || get_bcc(&pSMBr->hdr) < 2)
4615 /* If rc should we check for EOPNOSUPP and
4616 disable the srvino flag? or in caller? */
4617 rc = -EIO; /* bad smb */
4619 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4620 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4621 struct file_internal_info *pfinfo;
4622 /* BB Do we need a cast or hash here ? */
4624 cFYI(1, "Illegal size ret in QryIntrnlInf");
4626 goto GetInodeNumOut;
4628 pfinfo = (struct file_internal_info *)
4629 (data_offset + (char *) &pSMBr->hdr.Protocol);
4630 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4634 cifs_buf_release(pSMB);
4636 goto GetInodeNumberRetry;
4640 /* parses DFS refferal V3 structure
4641 * caller is responsible for freeing target_nodes
4644 * on failure - errno
4647 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4648 unsigned int *num_of_nodes,
4649 struct dfs_info3_param **target_nodes,
4650 const struct nls_table *nls_codepage, int remap,
4651 const char *searchName)
4656 struct dfs_referral_level_3 *ref;
4658 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4662 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4664 if (*num_of_nodes < 1) {
4665 cERROR(1, "num_referrals: must be at least > 0,"
4666 "but we get num_referrals = %d", *num_of_nodes);
4668 goto parse_DFS_referrals_exit;
4671 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4672 if (ref->VersionNumber != cpu_to_le16(3)) {
4673 cERROR(1, "Referrals of V%d version are not supported,"
4674 "should be V3", le16_to_cpu(ref->VersionNumber));
4676 goto parse_DFS_referrals_exit;
4679 /* get the upper boundary of the resp buffer */
4680 data_end = (char *)(&(pSMBr->PathConsumed)) +
4681 le16_to_cpu(pSMBr->t2.DataCount);
4683 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4685 le32_to_cpu(pSMBr->DFSFlags));
4687 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4688 *num_of_nodes, GFP_KERNEL);
4689 if (*target_nodes == NULL) {
4690 cERROR(1, "Failed to allocate buffer for target_nodes");
4692 goto parse_DFS_referrals_exit;
4695 /* collect necessary data from referrals */
4696 for (i = 0; i < *num_of_nodes; i++) {
4699 struct dfs_info3_param *node = (*target_nodes)+i;
4701 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4703 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4707 goto parse_DFS_referrals_exit;
4709 cifsConvertToUTF16((__le16 *) tmp, searchName,
4710 PATH_MAX, nls_codepage, remap);
4711 node->path_consumed = cifs_utf16_bytes(tmp,
4712 le16_to_cpu(pSMBr->PathConsumed),
4716 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4718 node->server_type = le16_to_cpu(ref->ServerType);
4719 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4722 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4723 max_len = data_end - temp;
4724 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4725 is_unicode, nls_codepage);
4726 if (!node->path_name) {
4728 goto parse_DFS_referrals_exit;
4731 /* copy link target UNC */
4732 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4733 max_len = data_end - temp;
4734 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4735 is_unicode, nls_codepage);
4736 if (!node->node_name) {
4738 goto parse_DFS_referrals_exit;
4744 parse_DFS_referrals_exit:
4746 free_dfs_info_array(*target_nodes, *num_of_nodes);
4747 *target_nodes = NULL;
4754 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4755 const char *search_name, struct dfs_info3_param **target_nodes,
4756 unsigned int *num_of_nodes,
4757 const struct nls_table *nls_codepage, int remap)
4759 /* TRANS2_GET_DFS_REFERRAL */
4760 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4761 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4765 __u16 params, byte_count;
4767 *target_nodes = NULL;
4769 cFYI(1, "In GetDFSRefer the path %s", search_name);
4773 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4778 /* server pointer checked in called function,
4779 but should never be null here anyway */
4780 pSMB->hdr.Mid = get_next_mid(ses->server);
4781 pSMB->hdr.Tid = ses->ipc_tid;
4782 pSMB->hdr.Uid = ses->Suid;
4783 if (ses->capabilities & CAP_STATUS32)
4784 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4785 if (ses->capabilities & CAP_DFS)
4786 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4788 if (ses->capabilities & CAP_UNICODE) {
4789 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4791 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4792 search_name, PATH_MAX, nls_codepage,
4794 name_len++; /* trailing null */
4796 } else { /* BB improve the check for buffer overruns BB */
4797 name_len = strnlen(search_name, PATH_MAX);
4798 name_len++; /* trailing null */
4799 strncpy(pSMB->RequestFileName, search_name, name_len);
4803 if (ses->server->sec_mode &
4804 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4805 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4808 pSMB->hdr.Uid = ses->Suid;
4810 params = 2 /* level */ + name_len /*includes null */ ;
4811 pSMB->TotalDataCount = 0;
4812 pSMB->DataCount = 0;
4813 pSMB->DataOffset = 0;
4814 pSMB->MaxParameterCount = 0;
4815 /* BB find exact max SMB PDU from sess structure BB */
4816 pSMB->MaxDataCount = cpu_to_le16(4000);
4817 pSMB->MaxSetupCount = 0;
4821 pSMB->Reserved2 = 0;
4822 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4823 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4824 pSMB->SetupCount = 1;
4825 pSMB->Reserved3 = 0;
4826 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4827 byte_count = params + 3 /* pad */ ;
4828 pSMB->ParameterCount = cpu_to_le16(params);
4829 pSMB->TotalParameterCount = pSMB->ParameterCount;
4830 pSMB->MaxReferralLevel = cpu_to_le16(3);
4831 inc_rfc1001_len(pSMB, byte_count);
4832 pSMB->ByteCount = cpu_to_le16(byte_count);
4834 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4837 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4840 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4842 /* BB Also check if enough total bytes returned? */
4843 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4844 rc = -EIO; /* bad smb */
4848 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4849 get_bcc(&pSMBr->hdr),
4850 le16_to_cpu(pSMBr->t2.DataOffset));
4852 /* parse returned result into more usable form */
4853 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4854 target_nodes, nls_codepage, remap,
4858 cifs_buf_release(pSMB);
4866 /* Query File System Info such as free space to old servers such as Win 9x */
4868 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4869 struct kstatfs *FSData)
4871 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4872 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4873 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4874 FILE_SYSTEM_ALLOC_INFO *response_data;
4876 int bytes_returned = 0;
4877 __u16 params, byte_count;
4879 cFYI(1, "OldQFSInfo");
4881 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4886 params = 2; /* level */
4887 pSMB->TotalDataCount = 0;
4888 pSMB->MaxParameterCount = cpu_to_le16(2);
4889 pSMB->MaxDataCount = cpu_to_le16(1000);
4890 pSMB->MaxSetupCount = 0;
4894 pSMB->Reserved2 = 0;
4895 byte_count = params + 1 /* pad */ ;
4896 pSMB->TotalParameterCount = cpu_to_le16(params);
4897 pSMB->ParameterCount = pSMB->TotalParameterCount;
4898 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4899 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4900 pSMB->DataCount = 0;
4901 pSMB->DataOffset = 0;
4902 pSMB->SetupCount = 1;
4903 pSMB->Reserved3 = 0;
4904 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4905 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4906 inc_rfc1001_len(pSMB, byte_count);
4907 pSMB->ByteCount = cpu_to_le16(byte_count);
4909 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4910 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4912 cFYI(1, "Send error in QFSInfo = %d", rc);
4913 } else { /* decode response */
4914 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4916 if (rc || get_bcc(&pSMBr->hdr) < 18)
4917 rc = -EIO; /* bad smb */
4919 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4920 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4921 get_bcc(&pSMBr->hdr), data_offset);
4923 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4924 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4926 le16_to_cpu(response_data->BytesPerSector) *
4927 le32_to_cpu(response_data->
4928 SectorsPerAllocationUnit);
4930 le32_to_cpu(response_data->TotalAllocationUnits);
4931 FSData->f_bfree = FSData->f_bavail =
4932 le32_to_cpu(response_data->FreeAllocationUnits);
4933 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4934 (unsigned long long)FSData->f_blocks,
4935 (unsigned long long)FSData->f_bfree,
4939 cifs_buf_release(pSMB);
4942 goto oldQFSInfoRetry;
4948 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4949 struct kstatfs *FSData)
4951 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4952 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4953 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4954 FILE_SYSTEM_INFO *response_data;
4956 int bytes_returned = 0;
4957 __u16 params, byte_count;
4959 cFYI(1, "In QFSInfo");
4961 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4966 params = 2; /* level */
4967 pSMB->TotalDataCount = 0;
4968 pSMB->MaxParameterCount = cpu_to_le16(2);
4969 pSMB->MaxDataCount = cpu_to_le16(1000);
4970 pSMB->MaxSetupCount = 0;
4974 pSMB->Reserved2 = 0;
4975 byte_count = params + 1 /* pad */ ;
4976 pSMB->TotalParameterCount = cpu_to_le16(params);
4977 pSMB->ParameterCount = pSMB->TotalParameterCount;
4978 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4979 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4980 pSMB->DataCount = 0;
4981 pSMB->DataOffset = 0;
4982 pSMB->SetupCount = 1;
4983 pSMB->Reserved3 = 0;
4984 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4985 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4986 inc_rfc1001_len(pSMB, byte_count);
4987 pSMB->ByteCount = cpu_to_le16(byte_count);
4989 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4990 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4992 cFYI(1, "Send error in QFSInfo = %d", rc);
4993 } else { /* decode response */
4994 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4996 if (rc || get_bcc(&pSMBr->hdr) < 24)
4997 rc = -EIO; /* bad smb */
4999 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5003 *) (((char *) &pSMBr->hdr.Protocol) +
5006 le32_to_cpu(response_data->BytesPerSector) *
5007 le32_to_cpu(response_data->
5008 SectorsPerAllocationUnit);
5010 le64_to_cpu(response_data->TotalAllocationUnits);
5011 FSData->f_bfree = FSData->f_bavail =
5012 le64_to_cpu(response_data->FreeAllocationUnits);
5013 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5014 (unsigned long long)FSData->f_blocks,
5015 (unsigned long long)FSData->f_bfree,
5019 cifs_buf_release(pSMB);
5028 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5030 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5031 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5032 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5033 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5035 int bytes_returned = 0;
5036 __u16 params, byte_count;
5038 cFYI(1, "In QFSAttributeInfo");
5040 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5045 params = 2; /* level */
5046 pSMB->TotalDataCount = 0;
5047 pSMB->MaxParameterCount = cpu_to_le16(2);
5048 /* BB find exact max SMB PDU from sess structure BB */
5049 pSMB->MaxDataCount = cpu_to_le16(1000);
5050 pSMB->MaxSetupCount = 0;
5054 pSMB->Reserved2 = 0;
5055 byte_count = params + 1 /* pad */ ;
5056 pSMB->TotalParameterCount = cpu_to_le16(params);
5057 pSMB->ParameterCount = pSMB->TotalParameterCount;
5058 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5059 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5060 pSMB->DataCount = 0;
5061 pSMB->DataOffset = 0;
5062 pSMB->SetupCount = 1;
5063 pSMB->Reserved3 = 0;
5064 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5065 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5066 inc_rfc1001_len(pSMB, byte_count);
5067 pSMB->ByteCount = cpu_to_le16(byte_count);
5069 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5070 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5072 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5073 } else { /* decode response */
5074 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5076 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5077 /* BB also check if enough bytes returned */
5078 rc = -EIO; /* bad smb */
5080 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5082 (FILE_SYSTEM_ATTRIBUTE_INFO
5083 *) (((char *) &pSMBr->hdr.Protocol) +
5085 memcpy(&tcon->fsAttrInfo, response_data,
5086 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5089 cifs_buf_release(pSMB);
5092 goto QFSAttributeRetry;
5098 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5100 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5101 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5102 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5103 FILE_SYSTEM_DEVICE_INFO *response_data;
5105 int bytes_returned = 0;
5106 __u16 params, byte_count;
5108 cFYI(1, "In QFSDeviceInfo");
5110 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5115 params = 2; /* level */
5116 pSMB->TotalDataCount = 0;
5117 pSMB->MaxParameterCount = cpu_to_le16(2);
5118 /* BB find exact max SMB PDU from sess structure BB */
5119 pSMB->MaxDataCount = cpu_to_le16(1000);
5120 pSMB->MaxSetupCount = 0;
5124 pSMB->Reserved2 = 0;
5125 byte_count = params + 1 /* pad */ ;
5126 pSMB->TotalParameterCount = cpu_to_le16(params);
5127 pSMB->ParameterCount = pSMB->TotalParameterCount;
5128 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5129 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5131 pSMB->DataCount = 0;
5132 pSMB->DataOffset = 0;
5133 pSMB->SetupCount = 1;
5134 pSMB->Reserved3 = 0;
5135 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5136 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5137 inc_rfc1001_len(pSMB, byte_count);
5138 pSMB->ByteCount = cpu_to_le16(byte_count);
5140 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5141 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5143 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5144 } else { /* decode response */
5145 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5147 if (rc || get_bcc(&pSMBr->hdr) <
5148 sizeof(FILE_SYSTEM_DEVICE_INFO))
5149 rc = -EIO; /* bad smb */
5151 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5153 (FILE_SYSTEM_DEVICE_INFO *)
5154 (((char *) &pSMBr->hdr.Protocol) +
5156 memcpy(&tcon->fsDevInfo, response_data,
5157 sizeof(FILE_SYSTEM_DEVICE_INFO));
5160 cifs_buf_release(pSMB);
5163 goto QFSDeviceRetry;
5169 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5171 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5172 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5173 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5174 FILE_SYSTEM_UNIX_INFO *response_data;
5176 int bytes_returned = 0;
5177 __u16 params, byte_count;
5179 cFYI(1, "In QFSUnixInfo");
5181 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5182 (void **) &pSMB, (void **) &pSMBr);
5186 params = 2; /* level */
5187 pSMB->TotalDataCount = 0;
5188 pSMB->DataCount = 0;
5189 pSMB->DataOffset = 0;
5190 pSMB->MaxParameterCount = cpu_to_le16(2);
5191 /* BB find exact max SMB PDU from sess structure BB */
5192 pSMB->MaxDataCount = cpu_to_le16(100);
5193 pSMB->MaxSetupCount = 0;
5197 pSMB->Reserved2 = 0;
5198 byte_count = params + 1 /* pad */ ;
5199 pSMB->ParameterCount = cpu_to_le16(params);
5200 pSMB->TotalParameterCount = pSMB->ParameterCount;
5201 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5202 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5203 pSMB->SetupCount = 1;
5204 pSMB->Reserved3 = 0;
5205 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5206 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5207 inc_rfc1001_len(pSMB, byte_count);
5208 pSMB->ByteCount = cpu_to_le16(byte_count);
5210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5213 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5214 } else { /* decode response */
5215 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5217 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5218 rc = -EIO; /* bad smb */
5220 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5222 (FILE_SYSTEM_UNIX_INFO
5223 *) (((char *) &pSMBr->hdr.Protocol) +
5225 memcpy(&tcon->fsUnixInfo, response_data,
5226 sizeof(FILE_SYSTEM_UNIX_INFO));
5229 cifs_buf_release(pSMB);
5239 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5241 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5242 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5243 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5245 int bytes_returned = 0;
5246 __u16 params, param_offset, offset, byte_count;
5248 cFYI(1, "In SETFSUnixInfo");
5250 /* BB switch to small buf init to save memory */
5251 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5252 (void **) &pSMB, (void **) &pSMBr);
5256 params = 4; /* 2 bytes zero followed by info level. */
5257 pSMB->MaxSetupCount = 0;
5261 pSMB->Reserved2 = 0;
5262 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5264 offset = param_offset + params;
5266 pSMB->MaxParameterCount = cpu_to_le16(4);
5267 /* BB find exact max SMB PDU from sess structure BB */
5268 pSMB->MaxDataCount = cpu_to_le16(100);
5269 pSMB->SetupCount = 1;
5270 pSMB->Reserved3 = 0;
5271 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5272 byte_count = 1 /* pad */ + params + 12;
5274 pSMB->DataCount = cpu_to_le16(12);
5275 pSMB->ParameterCount = cpu_to_le16(params);
5276 pSMB->TotalDataCount = pSMB->DataCount;
5277 pSMB->TotalParameterCount = pSMB->ParameterCount;
5278 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5279 pSMB->DataOffset = cpu_to_le16(offset);
5283 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5286 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5287 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5288 pSMB->ClientUnixCap = cpu_to_le64(cap);
5290 inc_rfc1001_len(pSMB, byte_count);
5291 pSMB->ByteCount = cpu_to_le16(byte_count);
5293 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5294 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5296 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5297 } else { /* decode response */
5298 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5300 rc = -EIO; /* bad smb */
5302 cifs_buf_release(pSMB);
5305 goto SETFSUnixRetry;
5313 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5314 struct kstatfs *FSData)
5316 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5317 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5318 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5319 FILE_SYSTEM_POSIX_INFO *response_data;
5321 int bytes_returned = 0;
5322 __u16 params, byte_count;
5324 cFYI(1, "In QFSPosixInfo");
5326 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5331 params = 2; /* level */
5332 pSMB->TotalDataCount = 0;
5333 pSMB->DataCount = 0;
5334 pSMB->DataOffset = 0;
5335 pSMB->MaxParameterCount = cpu_to_le16(2);
5336 /* BB find exact max SMB PDU from sess structure BB */
5337 pSMB->MaxDataCount = cpu_to_le16(100);
5338 pSMB->MaxSetupCount = 0;
5342 pSMB->Reserved2 = 0;
5343 byte_count = params + 1 /* pad */ ;
5344 pSMB->ParameterCount = cpu_to_le16(params);
5345 pSMB->TotalParameterCount = pSMB->ParameterCount;
5346 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5347 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5348 pSMB->SetupCount = 1;
5349 pSMB->Reserved3 = 0;
5350 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5351 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5352 inc_rfc1001_len(pSMB, byte_count);
5353 pSMB->ByteCount = cpu_to_le16(byte_count);
5355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5356 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5358 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5359 } else { /* decode response */
5360 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5362 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5363 rc = -EIO; /* bad smb */
5365 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5367 (FILE_SYSTEM_POSIX_INFO
5368 *) (((char *) &pSMBr->hdr.Protocol) +
5371 le32_to_cpu(response_data->BlockSize);
5373 le64_to_cpu(response_data->TotalBlocks);
5375 le64_to_cpu(response_data->BlocksAvail);
5376 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5377 FSData->f_bavail = FSData->f_bfree;
5380 le64_to_cpu(response_data->UserBlocksAvail);
5382 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5384 le64_to_cpu(response_data->TotalFileNodes);
5385 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5387 le64_to_cpu(response_data->FreeFileNodes);
5390 cifs_buf_release(pSMB);
5400 * We can not use write of zero bytes trick to set file size due to need for
5401 * large file support. Also note that this SetPathInfo is preferred to
5402 * SetFileInfo based method in next routine which is only needed to work around
5403 * a sharing violation bugin Samba which this routine can run into.
5406 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5407 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5408 bool set_allocation)
5410 struct smb_com_transaction2_spi_req *pSMB = NULL;
5411 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5412 struct file_end_of_file_info *parm_data;
5415 int bytes_returned = 0;
5416 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
5418 __u16 params, byte_count, data_count, param_offset, offset;
5420 cFYI(1, "In SetEOF");
5422 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5427 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5429 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5430 PATH_MAX, cifs_sb->local_nls, remap);
5431 name_len++; /* trailing null */
5433 } else { /* BB improve the check for buffer overruns BB */
5434 name_len = strnlen(file_name, PATH_MAX);
5435 name_len++; /* trailing null */
5436 strncpy(pSMB->FileName, file_name, name_len);
5438 params = 6 + name_len;
5439 data_count = sizeof(struct file_end_of_file_info);
5440 pSMB->MaxParameterCount = cpu_to_le16(2);
5441 pSMB->MaxDataCount = cpu_to_le16(4100);
5442 pSMB->MaxSetupCount = 0;
5446 pSMB->Reserved2 = 0;
5447 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5448 InformationLevel) - 4;
5449 offset = param_offset + params;
5450 if (set_allocation) {
5451 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5452 pSMB->InformationLevel =
5453 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5455 pSMB->InformationLevel =
5456 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5457 } else /* Set File Size */ {
5458 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5459 pSMB->InformationLevel =
5460 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5462 pSMB->InformationLevel =
5463 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5467 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5469 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5470 pSMB->DataOffset = cpu_to_le16(offset);
5471 pSMB->SetupCount = 1;
5472 pSMB->Reserved3 = 0;
5473 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5474 byte_count = 3 /* pad */ + params + data_count;
5475 pSMB->DataCount = cpu_to_le16(data_count);
5476 pSMB->TotalDataCount = pSMB->DataCount;
5477 pSMB->ParameterCount = cpu_to_le16(params);
5478 pSMB->TotalParameterCount = pSMB->ParameterCount;
5479 pSMB->Reserved4 = 0;
5480 inc_rfc1001_len(pSMB, byte_count);
5481 parm_data->FileSize = cpu_to_le64(size);
5482 pSMB->ByteCount = cpu_to_le16(byte_count);
5483 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5484 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5486 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5488 cifs_buf_release(pSMB);
5497 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5498 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5500 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5501 struct file_end_of_file_info *parm_data;
5503 __u16 params, param_offset, offset, byte_count, count;
5505 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5507 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5512 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5513 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5516 pSMB->MaxSetupCount = 0;
5520 pSMB->Reserved2 = 0;
5521 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5522 offset = param_offset + params;
5524 count = sizeof(struct file_end_of_file_info);
5525 pSMB->MaxParameterCount = cpu_to_le16(2);
5526 /* BB find exact max SMB PDU from sess structure BB */
5527 pSMB->MaxDataCount = cpu_to_le16(1000);
5528 pSMB->SetupCount = 1;
5529 pSMB->Reserved3 = 0;
5530 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5531 byte_count = 3 /* pad */ + params + count;
5532 pSMB->DataCount = cpu_to_le16(count);
5533 pSMB->ParameterCount = cpu_to_le16(params);
5534 pSMB->TotalDataCount = pSMB->DataCount;
5535 pSMB->TotalParameterCount = pSMB->ParameterCount;
5536 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5538 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5540 pSMB->DataOffset = cpu_to_le16(offset);
5541 parm_data->FileSize = cpu_to_le64(size);
5542 pSMB->Fid = cfile->fid.netfid;
5543 if (set_allocation) {
5544 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5545 pSMB->InformationLevel =
5546 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5548 pSMB->InformationLevel =
5549 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5550 } else /* Set File Size */ {
5551 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5552 pSMB->InformationLevel =
5553 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5555 pSMB->InformationLevel =
5556 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5558 pSMB->Reserved4 = 0;
5559 inc_rfc1001_len(pSMB, byte_count);
5560 pSMB->ByteCount = cpu_to_le16(byte_count);
5561 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5563 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5566 /* Note: On -EAGAIN error only caller can retry on handle based calls
5567 since file handle passed in no longer valid */
5572 /* Some legacy servers such as NT4 require that the file times be set on
5573 an open handle, rather than by pathname - this is awkward due to
5574 potential access conflicts on the open, but it is unavoidable for these
5575 old servers since the only other choice is to go from 100 nanosecond DCE
5576 time and resort to the original setpathinfo level which takes the ancient
5577 DOS time format with 2 second granularity */
5579 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5580 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5582 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5585 __u16 params, param_offset, offset, byte_count, count;
5587 cFYI(1, "Set Times (via SetFileInfo)");
5588 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5593 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5594 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5597 pSMB->MaxSetupCount = 0;
5601 pSMB->Reserved2 = 0;
5602 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5603 offset = param_offset + params;
5605 data_offset = (char *)pSMB +
5606 offsetof(struct smb_hdr, Protocol) + offset;
5608 count = sizeof(FILE_BASIC_INFO);
5609 pSMB->MaxParameterCount = cpu_to_le16(2);
5610 /* BB find max SMB PDU from sess */
5611 pSMB->MaxDataCount = cpu_to_le16(1000);
5612 pSMB->SetupCount = 1;
5613 pSMB->Reserved3 = 0;
5614 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5615 byte_count = 3 /* pad */ + params + count;
5616 pSMB->DataCount = cpu_to_le16(count);
5617 pSMB->ParameterCount = cpu_to_le16(params);
5618 pSMB->TotalDataCount = pSMB->DataCount;
5619 pSMB->TotalParameterCount = pSMB->ParameterCount;
5620 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5621 pSMB->DataOffset = cpu_to_le16(offset);
5623 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5624 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5626 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5627 pSMB->Reserved4 = 0;
5628 inc_rfc1001_len(pSMB, byte_count);
5629 pSMB->ByteCount = cpu_to_le16(byte_count);
5630 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5631 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5633 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5635 /* Note: On -EAGAIN error only caller can retry on handle based calls
5636 since file handle passed in no longer valid */
5642 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5643 bool delete_file, __u16 fid, __u32 pid_of_opener)
5645 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5648 __u16 params, param_offset, offset, byte_count, count;
5650 cFYI(1, "Set File Disposition (via SetFileInfo)");
5651 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5656 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5657 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5660 pSMB->MaxSetupCount = 0;
5664 pSMB->Reserved2 = 0;
5665 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5666 offset = param_offset + params;
5668 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5671 pSMB->MaxParameterCount = cpu_to_le16(2);
5672 /* BB find max SMB PDU from sess */
5673 pSMB->MaxDataCount = cpu_to_le16(1000);
5674 pSMB->SetupCount = 1;
5675 pSMB->Reserved3 = 0;
5676 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5677 byte_count = 3 /* pad */ + params + count;
5678 pSMB->DataCount = cpu_to_le16(count);
5679 pSMB->ParameterCount = cpu_to_le16(params);
5680 pSMB->TotalDataCount = pSMB->DataCount;
5681 pSMB->TotalParameterCount = pSMB->ParameterCount;
5682 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5683 pSMB->DataOffset = cpu_to_le16(offset);
5685 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5686 pSMB->Reserved4 = 0;
5687 inc_rfc1001_len(pSMB, byte_count);
5688 pSMB->ByteCount = cpu_to_le16(byte_count);
5689 *data_offset = delete_file ? 1 : 0;
5690 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5692 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5698 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5699 const char *fileName, const FILE_BASIC_INFO *data,
5700 const struct nls_table *nls_codepage, int remap)
5702 TRANSACTION2_SPI_REQ *pSMB = NULL;
5703 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5706 int bytes_returned = 0;
5708 __u16 params, param_offset, offset, byte_count, count;
5710 cFYI(1, "In SetTimes");
5713 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5718 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5720 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5721 PATH_MAX, nls_codepage, remap);
5722 name_len++; /* trailing null */
5724 } else { /* BB improve the check for buffer overruns BB */
5725 name_len = strnlen(fileName, PATH_MAX);
5726 name_len++; /* trailing null */
5727 strncpy(pSMB->FileName, fileName, name_len);
5730 params = 6 + name_len;
5731 count = sizeof(FILE_BASIC_INFO);
5732 pSMB->MaxParameterCount = cpu_to_le16(2);
5733 /* BB find max SMB PDU from sess structure BB */
5734 pSMB->MaxDataCount = cpu_to_le16(1000);
5735 pSMB->MaxSetupCount = 0;
5739 pSMB->Reserved2 = 0;
5740 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5741 InformationLevel) - 4;
5742 offset = param_offset + params;
5743 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5744 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5745 pSMB->DataOffset = cpu_to_le16(offset);
5746 pSMB->SetupCount = 1;
5747 pSMB->Reserved3 = 0;
5748 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5749 byte_count = 3 /* pad */ + params + count;
5751 pSMB->DataCount = cpu_to_le16(count);
5752 pSMB->ParameterCount = cpu_to_le16(params);
5753 pSMB->TotalDataCount = pSMB->DataCount;
5754 pSMB->TotalParameterCount = pSMB->ParameterCount;
5755 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5756 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5758 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5759 pSMB->Reserved4 = 0;
5760 inc_rfc1001_len(pSMB, byte_count);
5761 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5762 pSMB->ByteCount = cpu_to_le16(byte_count);
5763 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5764 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5766 cFYI(1, "SetPathInfo (times) returned %d", rc);
5768 cifs_buf_release(pSMB);
5776 /* Can not be used to set time stamps yet (due to old DOS time format) */
5777 /* Can be used to set attributes */
5778 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5779 handling it anyway and NT4 was what we thought it would be needed for
5780 Do not delete it until we prove whether needed for Win9x though */
5782 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5783 __u16 dos_attrs, const struct nls_table *nls_codepage)
5785 SETATTR_REQ *pSMB = NULL;
5786 SETATTR_RSP *pSMBr = NULL;
5791 cFYI(1, "In SetAttrLegacy");
5794 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5799 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5801 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5802 PATH_MAX, nls_codepage);
5803 name_len++; /* trailing null */
5805 } else { /* BB improve the check for buffer overruns BB */
5806 name_len = strnlen(fileName, PATH_MAX);
5807 name_len++; /* trailing null */
5808 strncpy(pSMB->fileName, fileName, name_len);
5810 pSMB->attr = cpu_to_le16(dos_attrs);
5811 pSMB->BufferFormat = 0x04;
5812 inc_rfc1001_len(pSMB, name_len + 1);
5813 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5814 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5815 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5817 cFYI(1, "Error in LegacySetAttr = %d", rc);
5819 cifs_buf_release(pSMB);
5822 goto SetAttrLgcyRetry;
5826 #endif /* temporarily unneeded SetAttr legacy function */
5829 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5830 const struct cifs_unix_set_info_args *args)
5832 u64 mode = args->mode;
5835 * Samba server ignores set of file size to zero due to bugs in some
5836 * older clients, but we should be precise - we use SetFileSize to
5837 * set file size and do not want to truncate file size to zero
5838 * accidentally as happened on one Samba server beta by putting
5839 * zero instead of -1 here
5841 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5842 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5843 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5844 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5845 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5846 data_offset->Uid = cpu_to_le64(args->uid);
5847 data_offset->Gid = cpu_to_le64(args->gid);
5848 /* better to leave device as zero when it is */
5849 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5850 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5851 data_offset->Permissions = cpu_to_le64(mode);
5854 data_offset->Type = cpu_to_le32(UNIX_FILE);
5855 else if (S_ISDIR(mode))
5856 data_offset->Type = cpu_to_le32(UNIX_DIR);
5857 else if (S_ISLNK(mode))
5858 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5859 else if (S_ISCHR(mode))
5860 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5861 else if (S_ISBLK(mode))
5862 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5863 else if (S_ISFIFO(mode))
5864 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5865 else if (S_ISSOCK(mode))
5866 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5870 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5871 const struct cifs_unix_set_info_args *args,
5872 u16 fid, u32 pid_of_opener)
5874 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5877 u16 params, param_offset, offset, byte_count, count;
5879 cFYI(1, "Set Unix Info (via SetFileInfo)");
5880 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5885 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5886 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5889 pSMB->MaxSetupCount = 0;
5893 pSMB->Reserved2 = 0;
5894 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5895 offset = param_offset + params;
5897 data_offset = (char *)pSMB +
5898 offsetof(struct smb_hdr, Protocol) + offset;
5900 count = sizeof(FILE_UNIX_BASIC_INFO);
5902 pSMB->MaxParameterCount = cpu_to_le16(2);
5903 /* BB find max SMB PDU from sess */
5904 pSMB->MaxDataCount = cpu_to_le16(1000);
5905 pSMB->SetupCount = 1;
5906 pSMB->Reserved3 = 0;
5907 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5908 byte_count = 3 /* pad */ + params + count;
5909 pSMB->DataCount = cpu_to_le16(count);
5910 pSMB->ParameterCount = cpu_to_le16(params);
5911 pSMB->TotalDataCount = pSMB->DataCount;
5912 pSMB->TotalParameterCount = pSMB->ParameterCount;
5913 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5914 pSMB->DataOffset = cpu_to_le16(offset);
5916 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5917 pSMB->Reserved4 = 0;
5918 inc_rfc1001_len(pSMB, byte_count);
5919 pSMB->ByteCount = cpu_to_le16(byte_count);
5921 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5923 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5925 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5927 /* Note: On -EAGAIN error only caller can retry on handle based calls
5928 since file handle passed in no longer valid */
5934 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5935 const char *file_name,
5936 const struct cifs_unix_set_info_args *args,
5937 const struct nls_table *nls_codepage, int remap)
5939 TRANSACTION2_SPI_REQ *pSMB = NULL;
5940 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5943 int bytes_returned = 0;
5944 FILE_UNIX_BASIC_INFO *data_offset;
5945 __u16 params, param_offset, offset, count, byte_count;
5947 cFYI(1, "In SetUID/GID/Mode");
5949 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5956 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5957 PATH_MAX, nls_codepage, remap);
5958 name_len++; /* trailing null */
5960 } else { /* BB improve the check for buffer overruns BB */
5961 name_len = strnlen(file_name, PATH_MAX);
5962 name_len++; /* trailing null */
5963 strncpy(pSMB->FileName, file_name, name_len);
5966 params = 6 + name_len;
5967 count = sizeof(FILE_UNIX_BASIC_INFO);
5968 pSMB->MaxParameterCount = cpu_to_le16(2);
5969 /* BB find max SMB PDU from sess structure BB */
5970 pSMB->MaxDataCount = cpu_to_le16(1000);
5971 pSMB->MaxSetupCount = 0;
5975 pSMB->Reserved2 = 0;
5976 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5977 InformationLevel) - 4;
5978 offset = param_offset + params;
5980 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5982 memset(data_offset, 0, count);
5983 pSMB->DataOffset = cpu_to_le16(offset);
5984 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5985 pSMB->SetupCount = 1;
5986 pSMB->Reserved3 = 0;
5987 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5988 byte_count = 3 /* pad */ + params + count;
5989 pSMB->ParameterCount = cpu_to_le16(params);
5990 pSMB->DataCount = cpu_to_le16(count);
5991 pSMB->TotalParameterCount = pSMB->ParameterCount;
5992 pSMB->TotalDataCount = pSMB->DataCount;
5993 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5994 pSMB->Reserved4 = 0;
5995 inc_rfc1001_len(pSMB, byte_count);
5997 cifs_fill_unix_set_info(data_offset, args);
5999 pSMB->ByteCount = cpu_to_le16(byte_count);
6000 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6001 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6003 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6005 cifs_buf_release(pSMB);
6011 #ifdef CONFIG_CIFS_XATTR
6013 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6014 * function used by listxattr and getxattr type calls. When ea_name is set,
6015 * it looks for that attribute name and stuffs that value into the EAData
6016 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6017 * buffer. In both cases, the return value is either the length of the
6018 * resulting data or a negative error code. If EAData is a NULL pointer then
6019 * the data isn't copied to it, but the length is returned.
6022 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6023 const unsigned char *searchName, const unsigned char *ea_name,
6024 char *EAData, size_t buf_size,
6025 const struct nls_table *nls_codepage, int remap)
6027 /* BB assumes one setup word */
6028 TRANSACTION2_QPI_REQ *pSMB = NULL;
6029 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6033 struct fealist *ea_response_data;
6034 struct fea *temp_fea;
6037 __u16 params, byte_count, data_offset;
6038 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6040 cFYI(1, "In Query All EAs path %s", searchName);
6042 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6047 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6049 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6050 PATH_MAX, nls_codepage, remap);
6051 list_len++; /* trailing null */
6053 } else { /* BB improve the check for buffer overruns BB */
6054 list_len = strnlen(searchName, PATH_MAX);
6055 list_len++; /* trailing null */
6056 strncpy(pSMB->FileName, searchName, list_len);
6059 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6060 pSMB->TotalDataCount = 0;
6061 pSMB->MaxParameterCount = cpu_to_le16(2);
6062 /* BB find exact max SMB PDU from sess structure BB */
6063 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6064 pSMB->MaxSetupCount = 0;
6068 pSMB->Reserved2 = 0;
6069 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6070 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6071 pSMB->DataCount = 0;
6072 pSMB->DataOffset = 0;
6073 pSMB->SetupCount = 1;
6074 pSMB->Reserved3 = 0;
6075 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6076 byte_count = params + 1 /* pad */ ;
6077 pSMB->TotalParameterCount = cpu_to_le16(params);
6078 pSMB->ParameterCount = pSMB->TotalParameterCount;
6079 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6080 pSMB->Reserved4 = 0;
6081 inc_rfc1001_len(pSMB, byte_count);
6082 pSMB->ByteCount = cpu_to_le16(byte_count);
6084 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6085 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6087 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6092 /* BB also check enough total bytes returned */
6093 /* BB we need to improve the validity checking
6094 of these trans2 responses */
6096 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6097 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6098 rc = -EIO; /* bad smb */
6102 /* check that length of list is not more than bcc */
6103 /* check that each entry does not go beyond length
6105 /* check that each element of each entry does not
6106 go beyond end of list */
6107 /* validate_trans2_offsets() */
6108 /* BB check if start of smb + data_offset > &bcc+ bcc */
6110 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6111 ea_response_data = (struct fealist *)
6112 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6114 list_len = le32_to_cpu(ea_response_data->list_len);
6115 cFYI(1, "ea length %d", list_len);
6116 if (list_len <= 8) {
6117 cFYI(1, "empty EA list returned from server");
6121 /* make sure list_len doesn't go past end of SMB */
6122 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6123 if ((char *)ea_response_data + list_len > end_of_smb) {
6124 cFYI(1, "EA list appears to go beyond SMB");
6129 /* account for ea list len */
6131 temp_fea = ea_response_data->list;
6132 temp_ptr = (char *)temp_fea;
6133 while (list_len > 0) {
6134 unsigned int name_len;
6139 /* make sure we can read name_len and value_len */
6141 cFYI(1, "EA entry goes beyond length of list");
6146 name_len = temp_fea->name_len;
6147 value_len = le16_to_cpu(temp_fea->value_len);
6148 list_len -= name_len + 1 + value_len;
6150 cFYI(1, "EA entry goes beyond length of list");
6156 if (ea_name_len == name_len &&
6157 memcmp(ea_name, temp_ptr, name_len) == 0) {
6158 temp_ptr += name_len + 1;
6162 if ((size_t)value_len > buf_size) {
6166 memcpy(EAData, temp_ptr, value_len);
6170 /* account for prefix user. and trailing null */
6171 rc += (5 + 1 + name_len);
6172 if (rc < (int) buf_size) {
6173 memcpy(EAData, "user.", 5);
6175 memcpy(EAData, temp_ptr, name_len);
6177 /* null terminate name */
6180 } else if (buf_size == 0) {
6181 /* skip copy - calc size only */
6183 /* stop before overrun buffer */
6188 temp_ptr += name_len + 1 + value_len;
6189 temp_fea = (struct fea *)temp_ptr;
6192 /* didn't find the named attribute */
6197 cifs_buf_release(pSMB);
6205 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6206 const char *fileName, const char *ea_name, const void *ea_value,
6207 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6210 struct smb_com_transaction2_spi_req *pSMB = NULL;
6211 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6212 struct fealist *parm_data;
6215 int bytes_returned = 0;
6216 __u16 params, param_offset, byte_count, offset, count;
6218 cFYI(1, "In SetEA");
6220 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6225 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6227 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6228 PATH_MAX, nls_codepage, remap);
6229 name_len++; /* trailing null */
6231 } else { /* BB improve the check for buffer overruns BB */
6232 name_len = strnlen(fileName, PATH_MAX);
6233 name_len++; /* trailing null */
6234 strncpy(pSMB->FileName, fileName, name_len);
6237 params = 6 + name_len;
6239 /* done calculating parms using name_len of file name,
6240 now use name_len to calculate length of ea name
6241 we are going to create in the inode xattrs */
6242 if (ea_name == NULL)
6245 name_len = strnlen(ea_name, 255);
6247 count = sizeof(*parm_data) + ea_value_len + name_len;
6248 pSMB->MaxParameterCount = cpu_to_le16(2);
6249 /* BB find max SMB PDU from sess */
6250 pSMB->MaxDataCount = cpu_to_le16(1000);
6251 pSMB->MaxSetupCount = 0;
6255 pSMB->Reserved2 = 0;
6256 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6257 InformationLevel) - 4;
6258 offset = param_offset + params;
6259 pSMB->InformationLevel =
6260 cpu_to_le16(SMB_SET_FILE_EA);
6263 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6265 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6266 pSMB->DataOffset = cpu_to_le16(offset);
6267 pSMB->SetupCount = 1;
6268 pSMB->Reserved3 = 0;
6269 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6270 byte_count = 3 /* pad */ + params + count;
6271 pSMB->DataCount = cpu_to_le16(count);
6272 parm_data->list_len = cpu_to_le32(count);
6273 parm_data->list[0].EA_flags = 0;
6274 /* we checked above that name len is less than 255 */
6275 parm_data->list[0].name_len = (__u8)name_len;
6276 /* EA names are always ASCII */
6278 strncpy(parm_data->list[0].name, ea_name, name_len);
6279 parm_data->list[0].name[name_len] = 0;
6280 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6281 /* caller ensures that ea_value_len is less than 64K but
6282 we need to ensure that it fits within the smb */
6284 /*BB add length check to see if it would fit in
6285 negotiated SMB buffer size BB */
6286 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6288 memcpy(parm_data->list[0].name+name_len+1,
6289 ea_value, ea_value_len);
6291 pSMB->TotalDataCount = pSMB->DataCount;
6292 pSMB->ParameterCount = cpu_to_le16(params);
6293 pSMB->TotalParameterCount = pSMB->ParameterCount;
6294 pSMB->Reserved4 = 0;
6295 inc_rfc1001_len(pSMB, byte_count);
6296 pSMB->ByteCount = cpu_to_le16(byte_count);
6297 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6298 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6300 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6302 cifs_buf_release(pSMB);
6311 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6313 * Years ago the kernel added a "dnotify" function for Samba server,
6314 * to allow network clients (such as Windows) to display updated
6315 * lists of files in directory listings automatically when
6316 * files are added by one user when another user has the
6317 * same directory open on their desktop. The Linux cifs kernel
6318 * client hooked into the kernel side of this interface for
6319 * the same reason, but ironically when the VFS moved from
6320 * "dnotify" to "inotify" it became harder to plug in Linux
6321 * network file system clients (the most obvious use case
6322 * for notify interfaces is when multiple users can update
6323 * the contents of the same directory - exactly what network
6324 * file systems can do) although the server (Samba) could
6325 * still use it. For the short term we leave the worker
6326 * function ifdeffed out (below) until inotify is fixed
6327 * in the VFS to make it easier to plug in network file
6328 * system clients. If inotify turns out to be permanently
6329 * incompatible for network fs clients, we could instead simply
6330 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6332 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6333 const int notify_subdirs, const __u16 netfid,
6334 __u32 filter, struct file *pfile, int multishot,
6335 const struct nls_table *nls_codepage)
6338 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6339 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6340 struct dir_notify_req *dnotify_req;
6343 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6344 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6349 pSMB->TotalParameterCount = 0 ;
6350 pSMB->TotalDataCount = 0;
6351 pSMB->MaxParameterCount = cpu_to_le32(2);
6352 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6353 pSMB->MaxSetupCount = 4;
6355 pSMB->ParameterOffset = 0;
6356 pSMB->DataCount = 0;
6357 pSMB->DataOffset = 0;
6358 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6359 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6360 pSMB->ParameterCount = pSMB->TotalParameterCount;
6362 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6363 pSMB->Reserved2 = 0;
6364 pSMB->CompletionFilter = cpu_to_le32(filter);
6365 pSMB->Fid = netfid; /* file handle always le */
6366 pSMB->ByteCount = 0;
6368 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6369 (struct smb_hdr *)pSMBr, &bytes_returned,
6372 cFYI(1, "Error in Notify = %d", rc);
6374 /* Add file to outstanding requests */
6375 /* BB change to kmem cache alloc */
6376 dnotify_req = kmalloc(
6377 sizeof(struct dir_notify_req),
6380 dnotify_req->Pid = pSMB->hdr.Pid;
6381 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6382 dnotify_req->Mid = pSMB->hdr.Mid;
6383 dnotify_req->Tid = pSMB->hdr.Tid;
6384 dnotify_req->Uid = pSMB->hdr.Uid;
6385 dnotify_req->netfid = netfid;
6386 dnotify_req->pfile = pfile;
6387 dnotify_req->filter = filter;
6388 dnotify_req->multishot = multishot;
6389 spin_lock(&GlobalMid_Lock);
6390 list_add_tail(&dnotify_req->lhead,
6391 &GlobalDnotifyReqList);
6392 spin_unlock(&GlobalMid_Lock);
6396 cifs_buf_release(pSMB);
6399 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */