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)
728 struct smb_rqst rqst = { .rq_iov = &iov,
731 cFYI(1, "In echo request");
733 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
737 /* set up echo request */
738 smb->hdr.Tid = 0xffff;
739 smb->hdr.WordCount = 1;
740 put_unaligned_le16(1, &smb->EchoCount);
741 put_bcc(1, &smb->hdr);
743 inc_rfc1001_len(smb, 3);
745 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
747 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
748 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
750 cFYI(1, "Echo request failed: %d", rc);
752 cifs_small_buf_release(smb);
758 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
760 LOGOFF_ANDX_REQ *pSMB;
763 cFYI(1, "In SMBLogoff for session disconnect");
766 * BB: do we need to check validity of ses and server? They should
767 * always be valid since we have an active reference. If not, that
768 * should probably be a BUG()
770 if (!ses || !ses->server)
773 mutex_lock(&ses->session_mutex);
774 if (ses->need_reconnect)
775 goto session_already_dead; /* no need to send SMBlogoff if uid
776 already closed due to reconnect */
777 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
779 mutex_unlock(&ses->session_mutex);
783 pSMB->hdr.Mid = get_next_mid(ses->server);
785 if (ses->server->sec_mode &
786 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
787 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
789 pSMB->hdr.Uid = ses->Suid;
791 pSMB->AndXCommand = 0xFF;
792 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
793 session_already_dead:
794 mutex_unlock(&ses->session_mutex);
796 /* if session dead then we do not need to do ulogoff,
797 since server closed smb session, no sense reporting
805 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
806 const char *fileName, __u16 type,
807 const struct nls_table *nls_codepage, int remap)
809 TRANSACTION2_SPI_REQ *pSMB = NULL;
810 TRANSACTION2_SPI_RSP *pSMBr = NULL;
811 struct unlink_psx_rq *pRqD;
814 int bytes_returned = 0;
815 __u16 params, param_offset, offset, byte_count;
817 cFYI(1, "In POSIX delete");
819 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
824 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
826 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
827 PATH_MAX, nls_codepage, remap);
828 name_len++; /* trailing null */
830 } else { /* BB add path length overrun check */
831 name_len = strnlen(fileName, PATH_MAX);
832 name_len++; /* trailing null */
833 strncpy(pSMB->FileName, fileName, name_len);
836 params = 6 + name_len;
837 pSMB->MaxParameterCount = cpu_to_le16(2);
838 pSMB->MaxDataCount = 0; /* BB double check this with jra */
839 pSMB->MaxSetupCount = 0;
844 param_offset = offsetof(struct smb_com_transaction2_spi_req,
845 InformationLevel) - 4;
846 offset = param_offset + params;
848 /* Setup pointer to Request Data (inode type) */
849 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
850 pRqD->type = cpu_to_le16(type);
851 pSMB->ParameterOffset = cpu_to_le16(param_offset);
852 pSMB->DataOffset = cpu_to_le16(offset);
853 pSMB->SetupCount = 1;
855 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
856 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
858 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
859 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
860 pSMB->ParameterCount = cpu_to_le16(params);
861 pSMB->TotalParameterCount = pSMB->ParameterCount;
862 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
864 inc_rfc1001_len(pSMB, byte_count);
865 pSMB->ByteCount = cpu_to_le16(byte_count);
866 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
867 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
869 cFYI(1, "Posix delete returned %d", rc);
870 cifs_buf_release(pSMB);
872 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
881 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
882 struct cifs_sb_info *cifs_sb)
884 DELETE_FILE_REQ *pSMB = NULL;
885 DELETE_FILE_RSP *pSMBr = NULL;
889 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
892 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
897 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
898 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
899 PATH_MAX, cifs_sb->local_nls,
901 name_len++; /* trailing null */
903 } else { /* BB improve check for buffer overruns BB */
904 name_len = strnlen(name, PATH_MAX);
905 name_len++; /* trailing null */
906 strncpy(pSMB->fileName, name, name_len);
908 pSMB->SearchAttributes =
909 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
910 pSMB->BufferFormat = 0x04;
911 inc_rfc1001_len(pSMB, name_len + 1);
912 pSMB->ByteCount = cpu_to_le16(name_len + 1);
913 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
914 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
915 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
917 cFYI(1, "Error in RMFile = %d", rc);
919 cifs_buf_release(pSMB);
927 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
928 struct cifs_sb_info *cifs_sb)
930 DELETE_DIRECTORY_REQ *pSMB = NULL;
931 DELETE_DIRECTORY_RSP *pSMBr = NULL;
935 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
937 cFYI(1, "In CIFSSMBRmDir");
939 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
944 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
945 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
946 PATH_MAX, cifs_sb->local_nls,
948 name_len++; /* trailing null */
950 } else { /* BB improve check for buffer overruns BB */
951 name_len = strnlen(name, PATH_MAX);
952 name_len++; /* trailing null */
953 strncpy(pSMB->DirName, name, name_len);
956 pSMB->BufferFormat = 0x04;
957 inc_rfc1001_len(pSMB, name_len + 1);
958 pSMB->ByteCount = cpu_to_le16(name_len + 1);
959 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
960 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
961 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
963 cFYI(1, "Error in RMDir = %d", rc);
965 cifs_buf_release(pSMB);
972 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
973 struct cifs_sb_info *cifs_sb)
976 CREATE_DIRECTORY_REQ *pSMB = NULL;
977 CREATE_DIRECTORY_RSP *pSMBr = NULL;
980 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
982 cFYI(1, "In CIFSSMBMkDir");
984 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
989 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
990 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
991 PATH_MAX, cifs_sb->local_nls,
993 name_len++; /* trailing null */
995 } else { /* BB improve check for buffer overruns BB */
996 name_len = strnlen(name, PATH_MAX);
997 name_len++; /* trailing null */
998 strncpy(pSMB->DirName, name, name_len);
1001 pSMB->BufferFormat = 0x04;
1002 inc_rfc1001_len(pSMB, name_len + 1);
1003 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1004 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1005 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1006 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1008 cFYI(1, "Error in Mkdir = %d", rc);
1010 cifs_buf_release(pSMB);
1017 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1018 __u32 posix_flags, __u64 mode, __u16 *netfid,
1019 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1020 const char *name, const struct nls_table *nls_codepage,
1023 TRANSACTION2_SPI_REQ *pSMB = NULL;
1024 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1027 int bytes_returned = 0;
1028 __u16 params, param_offset, offset, byte_count, count;
1029 OPEN_PSX_REQ *pdata;
1030 OPEN_PSX_RSP *psx_rsp;
1032 cFYI(1, "In POSIX Create");
1034 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1039 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1041 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1042 PATH_MAX, nls_codepage, remap);
1043 name_len++; /* trailing null */
1045 } else { /* BB improve the check for buffer overruns BB */
1046 name_len = strnlen(name, PATH_MAX);
1047 name_len++; /* trailing null */
1048 strncpy(pSMB->FileName, name, name_len);
1051 params = 6 + name_len;
1052 count = sizeof(OPEN_PSX_REQ);
1053 pSMB->MaxParameterCount = cpu_to_le16(2);
1054 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1055 pSMB->MaxSetupCount = 0;
1059 pSMB->Reserved2 = 0;
1060 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1061 InformationLevel) - 4;
1062 offset = param_offset + params;
1063 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1064 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1065 pdata->Permissions = cpu_to_le64(mode);
1066 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1067 pdata->OpenFlags = cpu_to_le32(*pOplock);
1068 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1069 pSMB->DataOffset = cpu_to_le16(offset);
1070 pSMB->SetupCount = 1;
1071 pSMB->Reserved3 = 0;
1072 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1073 byte_count = 3 /* pad */ + params + count;
1075 pSMB->DataCount = cpu_to_le16(count);
1076 pSMB->ParameterCount = cpu_to_le16(params);
1077 pSMB->TotalDataCount = pSMB->DataCount;
1078 pSMB->TotalParameterCount = pSMB->ParameterCount;
1079 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1080 pSMB->Reserved4 = 0;
1081 inc_rfc1001_len(pSMB, byte_count);
1082 pSMB->ByteCount = cpu_to_le16(byte_count);
1083 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1084 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1086 cFYI(1, "Posix create returned %d", rc);
1087 goto psx_create_err;
1090 cFYI(1, "copying inode info");
1091 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1093 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1094 rc = -EIO; /* bad smb */
1095 goto psx_create_err;
1098 /* copy return information to pRetData */
1099 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1100 + le16_to_cpu(pSMBr->t2.DataOffset));
1102 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1104 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1105 /* Let caller know file was created so we can set the mode. */
1106 /* Do we care about the CreateAction in any other cases? */
1107 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1108 *pOplock |= CIFS_CREATE_ACTION;
1109 /* check to make sure response data is there */
1110 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1111 pRetData->Type = cpu_to_le32(-1); /* unknown */
1112 cFYI(DBG2, "unknown type");
1114 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1115 + sizeof(FILE_UNIX_BASIC_INFO)) {
1116 cERROR(1, "Open response data too small");
1117 pRetData->Type = cpu_to_le32(-1);
1118 goto psx_create_err;
1120 memcpy((char *) pRetData,
1121 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1122 sizeof(FILE_UNIX_BASIC_INFO));
1126 cifs_buf_release(pSMB);
1128 if (posix_flags & SMB_O_DIRECTORY)
1129 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1131 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1139 static __u16 convert_disposition(int disposition)
1143 switch (disposition) {
1144 case FILE_SUPERSEDE:
1145 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1148 ofun = SMBOPEN_OAPPEND;
1151 ofun = SMBOPEN_OCREATE;
1154 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1156 case FILE_OVERWRITE:
1157 ofun = SMBOPEN_OTRUNC;
1159 case FILE_OVERWRITE_IF:
1160 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1163 cFYI(1, "unknown disposition %d", disposition);
1164 ofun = SMBOPEN_OAPPEND; /* regular open */
1170 access_flags_to_smbopen_mode(const int access_flags)
1172 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1174 if (masked_flags == GENERIC_READ)
1175 return SMBOPEN_READ;
1176 else if (masked_flags == GENERIC_WRITE)
1177 return SMBOPEN_WRITE;
1179 /* just go for read/write */
1180 return SMBOPEN_READWRITE;
1184 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1185 const char *fileName, const int openDisposition,
1186 const int access_flags, const int create_options, __u16 *netfid,
1187 int *pOplock, FILE_ALL_INFO *pfile_info,
1188 const struct nls_table *nls_codepage, int remap)
1191 OPENX_REQ *pSMB = NULL;
1192 OPENX_RSP *pSMBr = NULL;
1198 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1203 pSMB->AndXCommand = 0xFF; /* none */
1205 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1206 count = 1; /* account for one byte pad to word boundary */
1208 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1209 fileName, PATH_MAX, nls_codepage, remap);
1210 name_len++; /* trailing null */
1212 } else { /* BB improve check for buffer overruns BB */
1213 count = 0; /* no pad */
1214 name_len = strnlen(fileName, PATH_MAX);
1215 name_len++; /* trailing null */
1216 strncpy(pSMB->fileName, fileName, name_len);
1218 if (*pOplock & REQ_OPLOCK)
1219 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1220 else if (*pOplock & REQ_BATCHOPLOCK)
1221 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1223 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1224 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1225 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1226 /* set file as system file if special file such
1227 as fifo and server expecting SFU style and
1228 no Unix extensions */
1230 if (create_options & CREATE_OPTION_SPECIAL)
1231 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1232 else /* BB FIXME BB */
1233 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1235 if (create_options & CREATE_OPTION_READONLY)
1236 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1239 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1240 CREATE_OPTIONS_MASK); */
1241 /* BB FIXME END BB */
1243 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1244 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1246 inc_rfc1001_len(pSMB, count);
1248 pSMB->ByteCount = cpu_to_le16(count);
1249 /* long_op set to 1 to allow for oplock break timeouts */
1250 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1251 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1252 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1254 cFYI(1, "Error in Open = %d", rc);
1256 /* BB verify if wct == 15 */
1258 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1260 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1261 /* Let caller know file was created so we can set the mode. */
1262 /* Do we care about the CreateAction in any other cases? */
1264 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1265 *pOplock |= CIFS_CREATE_ACTION; */
1269 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1270 pfile_info->LastAccessTime = 0; /* BB fixme */
1271 pfile_info->LastWriteTime = 0; /* BB fixme */
1272 pfile_info->ChangeTime = 0; /* BB fixme */
1273 pfile_info->Attributes =
1274 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1275 /* the file_info buf is endian converted by caller */
1276 pfile_info->AllocationSize =
1277 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1278 pfile_info->EndOfFile = pfile_info->AllocationSize;
1279 pfile_info->NumberOfLinks = cpu_to_le32(1);
1280 pfile_info->DeletePending = 0;
1284 cifs_buf_release(pSMB);
1291 CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1292 const char *fileName, const int openDisposition,
1293 const int access_flags, const int create_options, __u16 *netfid,
1294 int *pOplock, FILE_ALL_INFO *pfile_info,
1295 const struct nls_table *nls_codepage, int remap)
1298 OPEN_REQ *pSMB = NULL;
1299 OPEN_RSP *pSMBr = NULL;
1305 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1310 pSMB->AndXCommand = 0xFF; /* none */
1312 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1313 count = 1; /* account for one byte pad to word boundary */
1315 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1316 fileName, PATH_MAX, nls_codepage, remap);
1317 name_len++; /* trailing null */
1319 pSMB->NameLength = cpu_to_le16(name_len);
1320 } else { /* BB improve check for buffer overruns BB */
1321 count = 0; /* no pad */
1322 name_len = strnlen(fileName, PATH_MAX);
1323 name_len++; /* trailing null */
1324 pSMB->NameLength = cpu_to_le16(name_len);
1325 strncpy(pSMB->fileName, fileName, name_len);
1327 if (*pOplock & REQ_OPLOCK)
1328 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1329 else if (*pOplock & REQ_BATCHOPLOCK)
1330 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1331 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1332 pSMB->AllocationSize = 0;
1333 /* set file as system file if special file such
1334 as fifo and server expecting SFU style and
1335 no Unix extensions */
1336 if (create_options & CREATE_OPTION_SPECIAL)
1337 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1339 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1341 /* XP does not handle ATTR_POSIX_SEMANTICS */
1342 /* but it helps speed up case sensitive checks for other
1343 servers such as Samba */
1344 if (tcon->ses->capabilities & CAP_UNIX)
1345 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1347 if (create_options & CREATE_OPTION_READONLY)
1348 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1350 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1351 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1352 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1353 /* BB Expirement with various impersonation levels and verify */
1354 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1355 pSMB->SecurityFlags =
1356 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1359 inc_rfc1001_len(pSMB, count);
1361 pSMB->ByteCount = cpu_to_le16(count);
1362 /* long_op set to 1 to allow for oplock break timeouts */
1363 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1364 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1365 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1367 cFYI(1, "Error in Open = %d", rc);
1369 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1370 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1371 /* Let caller know file was created so we can set the mode. */
1372 /* Do we care about the CreateAction in any other cases? */
1373 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1374 *pOplock |= CIFS_CREATE_ACTION;
1376 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1377 36 /* CreationTime to Attributes */);
1378 /* the file_info buf is endian converted by caller */
1379 pfile_info->AllocationSize = pSMBr->AllocationSize;
1380 pfile_info->EndOfFile = pSMBr->EndOfFile;
1381 pfile_info->NumberOfLinks = cpu_to_le32(1);
1382 pfile_info->DeletePending = 0;
1386 cifs_buf_release(pSMB);
1393 * Discard any remaining data in the current SMB. To do this, we borrow the
1397 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1399 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1400 int remaining = rfclen + 4 - server->total_read;
1401 struct cifs_readdata *rdata = mid->callback_data;
1403 while (remaining > 0) {
1406 length = cifs_read_from_socket(server, server->bigbuf,
1407 min_t(unsigned int, remaining,
1408 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1411 server->total_read += length;
1412 remaining -= length;
1415 dequeue_mid(mid, rdata->result);
1420 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1423 unsigned int data_offset, data_len;
1424 struct cifs_readdata *rdata = mid->callback_data;
1425 char *buf = server->smallbuf;
1426 unsigned int buflen = get_rfc1002_length(buf) + 4;
1428 cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1429 mid->mid, rdata->offset, rdata->bytes);
1432 * read the rest of READ_RSP header (sans Data array), or whatever we
1433 * can if there's not enough data. At this point, we've read down to
1436 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1437 HEADER_SIZE(server) + 1;
1439 rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1440 rdata->iov[0].iov_len = len;
1442 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1445 server->total_read += length;
1447 /* Was the SMB read successful? */
1448 rdata->result = server->ops->map_error(buf, false);
1449 if (rdata->result != 0) {
1450 cFYI(1, "%s: server returned error %d", __func__,
1452 return cifs_readv_discard(server, mid);
1455 /* Is there enough to get to the rest of the READ_RSP header? */
1456 if (server->total_read < server->vals->read_rsp_size) {
1457 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1458 __func__, server->total_read,
1459 server->vals->read_rsp_size);
1460 rdata->result = -EIO;
1461 return cifs_readv_discard(server, mid);
1464 data_offset = server->ops->read_data_offset(buf) + 4;
1465 if (data_offset < server->total_read) {
1467 * win2k8 sometimes sends an offset of 0 when the read
1468 * is beyond the EOF. Treat it as if the data starts just after
1471 cFYI(1, "%s: data offset (%u) inside read response header",
1472 __func__, data_offset);
1473 data_offset = server->total_read;
1474 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1475 /* data_offset is beyond the end of smallbuf */
1476 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1477 __func__, data_offset);
1478 rdata->result = -EIO;
1479 return cifs_readv_discard(server, mid);
1482 cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1483 server->total_read, data_offset);
1485 len = data_offset - server->total_read;
1487 /* read any junk before data into the rest of smallbuf */
1488 rdata->iov[0].iov_base = buf + server->total_read;
1489 rdata->iov[0].iov_len = len;
1490 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1493 server->total_read += length;
1496 /* set up first iov for signature check */
1497 rdata->iov[0].iov_base = buf;
1498 rdata->iov[0].iov_len = server->total_read;
1499 cFYI(1, "0: iov_base=%p iov_len=%zu",
1500 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1502 /* how much data is in the response? */
1503 data_len = server->ops->read_data_length(buf);
1504 if (data_offset + data_len > buflen) {
1505 /* data_len is corrupt -- discard frame */
1506 rdata->result = -EIO;
1507 return cifs_readv_discard(server, mid);
1510 /* marshal up the page array */
1512 len = rdata->marshal_iov(rdata, data_len);
1516 /* issue the read if we have any iovecs left to fill */
1517 if (rdata->nr_iov > 1) {
1518 length = cifs_readv_from_socket(server, &rdata->iov[1],
1519 rdata->nr_iov - 1, len);
1522 server->total_read += length;
1527 rdata->bytes = length;
1529 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1532 /* discard anything left over */
1533 if (server->total_read < buflen)
1534 return cifs_readv_discard(server, mid);
1536 dequeue_mid(mid, false);
1541 cifs_readv_callback(struct mid_q_entry *mid)
1543 struct cifs_readdata *rdata = mid->callback_data;
1544 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1545 struct TCP_Server_Info *server = tcon->ses->server;
1546 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1547 .rq_nvec = rdata->nr_iov };
1549 cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1550 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1552 switch (mid->mid_state) {
1553 case MID_RESPONSE_RECEIVED:
1554 /* result already set, check signature */
1555 if (server->sec_mode &
1556 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1559 rc = cifs_verify_signature(&rqst, server,
1560 mid->sequence_number + 1);
1562 cERROR(1, "SMB signature verification returned "
1565 /* FIXME: should this be counted toward the initiating task? */
1566 task_io_account_read(rdata->bytes);
1567 cifs_stats_bytes_read(tcon, rdata->bytes);
1569 case MID_REQUEST_SUBMITTED:
1570 case MID_RETRY_NEEDED:
1571 rdata->result = -EAGAIN;
1574 rdata->result = -EIO;
1577 queue_work(cifsiod_wq, &rdata->work);
1578 DeleteMidQEntry(mid);
1579 add_credits(server, 1, 0);
1582 /* cifs_async_readv - send an async write, and set up mid to handle result */
1584 cifs_async_readv(struct cifs_readdata *rdata)
1587 READ_REQ *smb = NULL;
1589 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1590 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1593 cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1594 rdata->offset, rdata->bytes);
1596 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1599 wct = 10; /* old style read */
1600 if ((rdata->offset >> 32) > 0) {
1601 /* can not handle this big offset for old */
1606 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1610 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1611 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1613 smb->AndXCommand = 0xFF; /* none */
1614 smb->Fid = rdata->cfile->fid.netfid;
1615 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1617 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1619 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1620 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1624 /* old style read */
1625 struct smb_com_readx_req *smbr =
1626 (struct smb_com_readx_req *)smb;
1627 smbr->ByteCount = 0;
1630 /* 4 for RFC1001 length + 1 for BCC */
1631 rdata->iov[0].iov_base = smb;
1632 rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1634 kref_get(&rdata->refcount);
1635 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1636 cifs_readv_callback, rdata, 0);
1639 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1641 kref_put(&rdata->refcount, cifs_readdata_release);
1643 cifs_small_buf_release(smb);
1648 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1649 unsigned int *nbytes, char **buf, int *pbuf_type)
1652 READ_REQ *pSMB = NULL;
1653 READ_RSP *pSMBr = NULL;
1654 char *pReadData = NULL;
1656 int resp_buf_type = 0;
1658 __u32 pid = io_parms->pid;
1659 __u16 netfid = io_parms->netfid;
1660 __u64 offset = io_parms->offset;
1661 struct cifs_tcon *tcon = io_parms->tcon;
1662 unsigned int count = io_parms->length;
1664 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1665 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1668 wct = 10; /* old style read */
1669 if ((offset >> 32) > 0) {
1670 /* can not handle this big offset for old */
1676 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1680 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1681 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1683 /* tcon and ses pointer are checked in smb_init */
1684 if (tcon->ses->server == NULL)
1685 return -ECONNABORTED;
1687 pSMB->AndXCommand = 0xFF; /* none */
1689 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1691 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1693 pSMB->Remaining = 0;
1694 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1695 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1697 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1699 /* old style read */
1700 struct smb_com_readx_req *pSMBW =
1701 (struct smb_com_readx_req *)pSMB;
1702 pSMBW->ByteCount = 0;
1705 iov[0].iov_base = (char *)pSMB;
1706 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1707 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1708 &resp_buf_type, CIFS_LOG_ERROR);
1709 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1710 pSMBr = (READ_RSP *)iov[0].iov_base;
1712 cERROR(1, "Send error in read = %d", rc);
1714 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1715 data_length = data_length << 16;
1716 data_length += le16_to_cpu(pSMBr->DataLength);
1717 *nbytes = data_length;
1719 /*check that DataLength would not go beyond end of SMB */
1720 if ((data_length > CIFSMaxBufSize)
1721 || (data_length > count)) {
1722 cFYI(1, "bad length %d for count %d",
1723 data_length, count);
1727 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1728 le16_to_cpu(pSMBr->DataOffset);
1729 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1730 cERROR(1, "Faulting on read rc = %d",rc);
1732 }*/ /* can not use copy_to_user when using page cache*/
1734 memcpy(*buf, pReadData, data_length);
1738 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1740 if (resp_buf_type == CIFS_SMALL_BUFFER)
1741 cifs_small_buf_release(iov[0].iov_base);
1742 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1743 cifs_buf_release(iov[0].iov_base);
1744 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1745 /* return buffer to caller to free */
1746 *buf = iov[0].iov_base;
1747 if (resp_buf_type == CIFS_SMALL_BUFFER)
1748 *pbuf_type = CIFS_SMALL_BUFFER;
1749 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1750 *pbuf_type = CIFS_LARGE_BUFFER;
1751 } /* else no valid buffer on return - leave as null */
1753 /* Note: On -EAGAIN error only caller can retry on handle based calls
1754 since file handle passed in no longer valid */
1760 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1761 unsigned int *nbytes, const char *buf,
1762 const char __user *ubuf, const int long_op)
1765 WRITE_REQ *pSMB = NULL;
1766 WRITE_RSP *pSMBr = NULL;
1767 int bytes_returned, wct;
1770 __u32 pid = io_parms->pid;
1771 __u16 netfid = io_parms->netfid;
1772 __u64 offset = io_parms->offset;
1773 struct cifs_tcon *tcon = io_parms->tcon;
1774 unsigned int count = io_parms->length;
1778 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1779 if (tcon->ses == NULL)
1780 return -ECONNABORTED;
1782 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1786 if ((offset >> 32) > 0) {
1787 /* can not handle big offset for old srv */
1792 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1797 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1798 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1800 /* tcon and ses pointer are checked in smb_init */
1801 if (tcon->ses->server == NULL)
1802 return -ECONNABORTED;
1804 pSMB->AndXCommand = 0xFF; /* none */
1806 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1808 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1810 pSMB->Reserved = 0xFFFFFFFF;
1811 pSMB->WriteMode = 0;
1812 pSMB->Remaining = 0;
1814 /* Can increase buffer size if buffer is big enough in some cases ie we
1815 can send more if LARGE_WRITE_X capability returned by the server and if
1816 our buffer is big enough or if we convert to iovecs on socket writes
1817 and eliminate the copy to the CIFS buffer */
1818 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1819 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1821 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1825 if (bytes_sent > count)
1828 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1830 memcpy(pSMB->Data, buf, bytes_sent);
1832 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1833 cifs_buf_release(pSMB);
1836 } else if (count != 0) {
1838 cifs_buf_release(pSMB);
1840 } /* else setting file size with write of zero bytes */
1842 byte_count = bytes_sent + 1; /* pad */
1843 else /* wct == 12 */
1844 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1846 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1847 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1848 inc_rfc1001_len(pSMB, byte_count);
1851 pSMB->ByteCount = cpu_to_le16(byte_count);
1852 else { /* old style write has byte count 4 bytes earlier
1854 struct smb_com_writex_req *pSMBW =
1855 (struct smb_com_writex_req *)pSMB;
1856 pSMBW->ByteCount = cpu_to_le16(byte_count);
1859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1860 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1861 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1863 cFYI(1, "Send error in write = %d", rc);
1865 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1866 *nbytes = (*nbytes) << 16;
1867 *nbytes += le16_to_cpu(pSMBr->Count);
1870 * Mask off high 16 bits when bytes written as returned by the
1871 * server is greater than bytes requested by the client. Some
1872 * OS/2 servers are known to set incorrect CountHigh values.
1874 if (*nbytes > count)
1878 cifs_buf_release(pSMB);
1880 /* Note: On -EAGAIN error only caller can retry on handle based calls
1881 since file handle passed in no longer valid */
1887 cifs_writedata_release(struct kref *refcount)
1889 struct cifs_writedata *wdata = container_of(refcount,
1890 struct cifs_writedata, refcount);
1893 cifsFileInfo_put(wdata->cfile);
1899 * Write failed with a retryable error. Resend the write request. It's also
1900 * possible that the page was redirtied so re-clean the page.
1903 cifs_writev_requeue(struct cifs_writedata *wdata)
1906 struct inode *inode = wdata->cfile->dentry->d_inode;
1907 struct TCP_Server_Info *server;
1909 for (i = 0; i < wdata->nr_pages; i++) {
1910 lock_page(wdata->pages[i]);
1911 clear_page_dirty_for_io(wdata->pages[i]);
1915 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1916 rc = server->ops->async_writev(wdata);
1917 } while (rc == -EAGAIN);
1919 for (i = 0; i < wdata->nr_pages; i++) {
1921 SetPageError(wdata->pages[i]);
1922 unlock_page(wdata->pages[i]);
1925 mapping_set_error(inode->i_mapping, rc);
1926 kref_put(&wdata->refcount, cifs_writedata_release);
1930 cifs_writev_complete(struct work_struct *work)
1932 struct cifs_writedata *wdata = container_of(work,
1933 struct cifs_writedata, work);
1934 struct inode *inode = wdata->cfile->dentry->d_inode;
1937 if (wdata->result == 0) {
1938 spin_lock(&inode->i_lock);
1939 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1940 spin_unlock(&inode->i_lock);
1941 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1943 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1944 return cifs_writev_requeue(wdata);
1946 for (i = 0; i < wdata->nr_pages; i++) {
1947 struct page *page = wdata->pages[i];
1948 if (wdata->result == -EAGAIN)
1949 __set_page_dirty_nobuffers(page);
1950 else if (wdata->result < 0)
1952 end_page_writeback(page);
1953 page_cache_release(page);
1955 if (wdata->result != -EAGAIN)
1956 mapping_set_error(inode->i_mapping, wdata->result);
1957 kref_put(&wdata->refcount, cifs_writedata_release);
1960 struct cifs_writedata *
1961 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1963 struct cifs_writedata *wdata;
1965 /* this would overflow */
1966 if (nr_pages == 0) {
1967 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1971 /* writedata + number of page pointers */
1972 wdata = kzalloc(sizeof(*wdata) +
1973 sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1974 if (wdata != NULL) {
1975 kref_init(&wdata->refcount);
1976 INIT_LIST_HEAD(&wdata->list);
1977 init_completion(&wdata->done);
1978 INIT_WORK(&wdata->work, complete);
1984 * Check the mid_state and signature on received buffer (if any), and queue the
1985 * workqueue completion task.
1988 cifs_writev_callback(struct mid_q_entry *mid)
1990 struct cifs_writedata *wdata = mid->callback_data;
1991 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1992 unsigned int written;
1993 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1995 switch (mid->mid_state) {
1996 case MID_RESPONSE_RECEIVED:
1997 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1998 if (wdata->result != 0)
2001 written = le16_to_cpu(smb->CountHigh);
2003 written += le16_to_cpu(smb->Count);
2005 * Mask off high 16 bits when bytes written as returned
2006 * by the server is greater than bytes requested by the
2007 * client. OS/2 servers are known to set incorrect
2010 if (written > wdata->bytes)
2013 if (written < wdata->bytes)
2014 wdata->result = -ENOSPC;
2016 wdata->bytes = written;
2018 case MID_REQUEST_SUBMITTED:
2019 case MID_RETRY_NEEDED:
2020 wdata->result = -EAGAIN;
2023 wdata->result = -EIO;
2027 queue_work(cifsiod_wq, &wdata->work);
2028 DeleteMidQEntry(mid);
2029 add_credits(tcon->ses->server, 1, 0);
2032 /* cifs_async_writev - send an async write, and set up mid to handle result */
2034 cifs_async_writev(struct cifs_writedata *wdata)
2036 int i, rc = -EACCES;
2037 WRITE_REQ *smb = NULL;
2039 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2040 struct kvec *iov = NULL;
2041 struct smb_rqst rqst = { };
2043 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2047 if (wdata->offset >> 32 > 0) {
2048 /* can not handle big offset for old srv */
2053 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2055 goto async_writev_out;
2057 /* 1 iov per page + 1 for header */
2058 rqst.rq_nvec = wdata->nr_pages + 1;
2059 iov = kzalloc((rqst.rq_nvec) * sizeof(*iov), GFP_NOFS);
2062 goto async_writev_out;
2066 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2067 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2069 smb->AndXCommand = 0xFF; /* none */
2070 smb->Fid = wdata->cfile->fid.netfid;
2071 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2073 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2074 smb->Reserved = 0xFFFFFFFF;
2079 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2081 /* 4 for RFC1001 length + 1 for BCC */
2082 iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2083 iov[0].iov_base = smb;
2086 * This function should marshal up the page array into the kvec
2087 * array, reserving [0] for the header. It should kmap the pages
2088 * and set the iov_len properly for each one. It may also set
2092 wdata->marshal_iov(iov, wdata);
2095 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2097 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2098 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2101 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2102 put_bcc(wdata->bytes + 1, &smb->hdr);
2105 struct smb_com_writex_req *smbw =
2106 (struct smb_com_writex_req *)smb;
2107 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2108 put_bcc(wdata->bytes + 5, &smbw->hdr);
2109 iov[0].iov_len += 4; /* pad bigger by four bytes */
2112 kref_get(&wdata->refcount);
2113 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2114 cifs_writev_callback, wdata, 0);
2117 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2119 kref_put(&wdata->refcount, cifs_writedata_release);
2121 /* send is done, unmap pages */
2122 for (i = 0; i < wdata->nr_pages; i++)
2123 kunmap(wdata->pages[i]);
2126 cifs_small_buf_release(smb);
2132 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2133 unsigned int *nbytes, struct kvec *iov, int n_vec)
2136 WRITE_REQ *pSMB = NULL;
2139 int resp_buf_type = 0;
2140 __u32 pid = io_parms->pid;
2141 __u16 netfid = io_parms->netfid;
2142 __u64 offset = io_parms->offset;
2143 struct cifs_tcon *tcon = io_parms->tcon;
2144 unsigned int count = io_parms->length;
2148 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2150 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2154 if ((offset >> 32) > 0) {
2155 /* can not handle big offset for old srv */
2159 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2163 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2164 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2166 /* tcon and ses pointer are checked in smb_init */
2167 if (tcon->ses->server == NULL)
2168 return -ECONNABORTED;
2170 pSMB->AndXCommand = 0xFF; /* none */
2172 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2174 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2175 pSMB->Reserved = 0xFFFFFFFF;
2176 pSMB->WriteMode = 0;
2177 pSMB->Remaining = 0;
2180 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2182 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2183 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2184 /* header + 1 byte pad */
2185 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2187 inc_rfc1001_len(pSMB, count + 1);
2188 else /* wct == 12 */
2189 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2191 pSMB->ByteCount = cpu_to_le16(count + 1);
2192 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2193 struct smb_com_writex_req *pSMBW =
2194 (struct smb_com_writex_req *)pSMB;
2195 pSMBW->ByteCount = cpu_to_le16(count + 5);
2197 iov[0].iov_base = pSMB;
2199 iov[0].iov_len = smb_hdr_len + 4;
2200 else /* wct == 12 pad bigger by four bytes */
2201 iov[0].iov_len = smb_hdr_len + 8;
2204 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
2205 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2207 cFYI(1, "Send error Write2 = %d", rc);
2208 } else if (resp_buf_type == 0) {
2209 /* presumably this can not happen, but best to be safe */
2212 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2213 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2214 *nbytes = (*nbytes) << 16;
2215 *nbytes += le16_to_cpu(pSMBr->Count);
2218 * Mask off high 16 bits when bytes written as returned by the
2219 * server is greater than bytes requested by the client. OS/2
2220 * servers are known to set incorrect CountHigh values.
2222 if (*nbytes > count)
2226 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2227 if (resp_buf_type == CIFS_SMALL_BUFFER)
2228 cifs_small_buf_release(iov[0].iov_base);
2229 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2230 cifs_buf_release(iov[0].iov_base);
2232 /* Note: On -EAGAIN error only caller can retry on handle based calls
2233 since file handle passed in no longer valid */
2238 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2239 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2240 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2243 LOCK_REQ *pSMB = NULL;
2248 cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2250 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2255 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2256 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2257 pSMB->LockType = lock_type;
2258 pSMB->AndXCommand = 0xFF; /* none */
2259 pSMB->Fid = netfid; /* netfid stays le */
2261 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2262 inc_rfc1001_len(pSMB, count);
2263 pSMB->ByteCount = cpu_to_le16(count);
2265 iov[0].iov_base = (char *)pSMB;
2266 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2267 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2268 iov[1].iov_base = (char *)buf;
2269 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2271 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2272 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2274 cFYI(1, "Send error in cifs_lockv = %d", rc);
2280 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2281 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2282 const __u64 offset, const __u32 numUnlock,
2283 const __u32 numLock, const __u8 lockType,
2284 const bool waitFlag, const __u8 oplock_level)
2287 LOCK_REQ *pSMB = NULL;
2288 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2293 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2294 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2299 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2300 /* no response expected */
2301 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2303 } else if (waitFlag) {
2304 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2305 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2310 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2311 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2312 pSMB->LockType = lockType;
2313 pSMB->OplockLevel = oplock_level;
2314 pSMB->AndXCommand = 0xFF; /* none */
2315 pSMB->Fid = smb_file_id; /* netfid stays le */
2317 if ((numLock != 0) || (numUnlock != 0)) {
2318 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2319 /* BB where to store pid high? */
2320 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2321 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2322 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2323 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2324 count = sizeof(LOCKING_ANDX_RANGE);
2329 inc_rfc1001_len(pSMB, count);
2330 pSMB->ByteCount = cpu_to_le16(count);
2333 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2334 (struct smb_hdr *) pSMB, &bytes_returned);
2335 cifs_small_buf_release(pSMB);
2337 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2338 /* SMB buffer freed by function above */
2340 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2342 cFYI(1, "Send error in Lock = %d", rc);
2344 /* Note: On -EAGAIN error only caller can retry on handle based calls
2345 since file handle passed in no longer valid */
2350 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2351 const __u16 smb_file_id, const __u32 netpid,
2352 const loff_t start_offset, const __u64 len,
2353 struct file_lock *pLockData, const __u16 lock_type,
2354 const bool waitFlag)
2356 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2357 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2358 struct cifs_posix_lock *parm_data;
2361 int bytes_returned = 0;
2362 int resp_buf_type = 0;
2363 __u16 params, param_offset, offset, byte_count, count;
2366 cFYI(1, "Posix Lock");
2368 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2373 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2376 pSMB->MaxSetupCount = 0;
2379 pSMB->Reserved2 = 0;
2380 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2381 offset = param_offset + params;
2383 count = sizeof(struct cifs_posix_lock);
2384 pSMB->MaxParameterCount = cpu_to_le16(2);
2385 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2386 pSMB->SetupCount = 1;
2387 pSMB->Reserved3 = 0;
2389 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2391 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2392 byte_count = 3 /* pad */ + params + count;
2393 pSMB->DataCount = cpu_to_le16(count);
2394 pSMB->ParameterCount = cpu_to_le16(params);
2395 pSMB->TotalDataCount = pSMB->DataCount;
2396 pSMB->TotalParameterCount = pSMB->ParameterCount;
2397 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2398 parm_data = (struct cifs_posix_lock *)
2399 (((char *) &pSMB->hdr.Protocol) + offset);
2401 parm_data->lock_type = cpu_to_le16(lock_type);
2403 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2404 parm_data->lock_flags = cpu_to_le16(1);
2405 pSMB->Timeout = cpu_to_le32(-1);
2409 parm_data->pid = cpu_to_le32(netpid);
2410 parm_data->start = cpu_to_le64(start_offset);
2411 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2413 pSMB->DataOffset = cpu_to_le16(offset);
2414 pSMB->Fid = smb_file_id;
2415 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2416 pSMB->Reserved4 = 0;
2417 inc_rfc1001_len(pSMB, byte_count);
2418 pSMB->ByteCount = cpu_to_le16(byte_count);
2420 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2421 (struct smb_hdr *) pSMBr, &bytes_returned);
2423 iov[0].iov_base = (char *)pSMB;
2424 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2425 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2426 &resp_buf_type, timeout);
2427 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2428 not try to free it twice below on exit */
2429 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2433 cFYI(1, "Send error in Posix Lock = %d", rc);
2434 } else if (pLockData) {
2435 /* lock structure can be returned on get */
2438 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2440 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2441 rc = -EIO; /* bad smb */
2444 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2445 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2446 if (data_count < sizeof(struct cifs_posix_lock)) {
2450 parm_data = (struct cifs_posix_lock *)
2451 ((char *)&pSMBr->hdr.Protocol + data_offset);
2452 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2453 pLockData->fl_type = F_UNLCK;
2455 if (parm_data->lock_type ==
2456 __constant_cpu_to_le16(CIFS_RDLCK))
2457 pLockData->fl_type = F_RDLCK;
2458 else if (parm_data->lock_type ==
2459 __constant_cpu_to_le16(CIFS_WRLCK))
2460 pLockData->fl_type = F_WRLCK;
2462 pLockData->fl_start = le64_to_cpu(parm_data->start);
2463 pLockData->fl_end = pLockData->fl_start +
2464 le64_to_cpu(parm_data->length) - 1;
2465 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2471 cifs_small_buf_release(pSMB);
2473 if (resp_buf_type == CIFS_SMALL_BUFFER)
2474 cifs_small_buf_release(iov[0].iov_base);
2475 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2476 cifs_buf_release(iov[0].iov_base);
2478 /* Note: On -EAGAIN error only caller can retry on handle based calls
2479 since file handle passed in no longer valid */
2486 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2489 CLOSE_REQ *pSMB = NULL;
2490 cFYI(1, "In CIFSSMBClose");
2492 /* do not retry on dead session on close */
2493 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2499 pSMB->FileID = (__u16) smb_file_id;
2500 pSMB->LastWriteTime = 0xFFFFFFFF;
2501 pSMB->ByteCount = 0;
2502 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2503 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2506 /* EINTR is expected when user ctl-c to kill app */
2507 cERROR(1, "Send error in Close = %d", rc);
2511 /* Since session is dead, file will be closed on server already */
2519 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2522 FLUSH_REQ *pSMB = NULL;
2523 cFYI(1, "In CIFSSMBFlush");
2525 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2529 pSMB->FileID = (__u16) smb_file_id;
2530 pSMB->ByteCount = 0;
2531 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2532 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2534 cERROR(1, "Send error in Flush = %d", rc);
2540 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2541 const char *from_name, const char *to_name,
2542 struct cifs_sb_info *cifs_sb)
2545 RENAME_REQ *pSMB = NULL;
2546 RENAME_RSP *pSMBr = NULL;
2548 int name_len, name_len2;
2550 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2552 cFYI(1, "In CIFSSMBRename");
2554 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2559 pSMB->BufferFormat = 0x04;
2560 pSMB->SearchAttributes =
2561 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2564 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2565 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2566 from_name, PATH_MAX,
2567 cifs_sb->local_nls, remap);
2568 name_len++; /* trailing null */
2570 pSMB->OldFileName[name_len] = 0x04; /* pad */
2571 /* protocol requires ASCII signature byte on Unicode string */
2572 pSMB->OldFileName[name_len + 1] = 0x00;
2574 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2575 to_name, PATH_MAX, cifs_sb->local_nls,
2577 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2578 name_len2 *= 2; /* convert to bytes */
2579 } else { /* BB improve the check for buffer overruns BB */
2580 name_len = strnlen(from_name, PATH_MAX);
2581 name_len++; /* trailing null */
2582 strncpy(pSMB->OldFileName, from_name, name_len);
2583 name_len2 = strnlen(to_name, PATH_MAX);
2584 name_len2++; /* trailing null */
2585 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2586 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2587 name_len2++; /* trailing null */
2588 name_len2++; /* signature byte */
2591 count = 1 /* 1st signature byte */ + name_len + name_len2;
2592 inc_rfc1001_len(pSMB, count);
2593 pSMB->ByteCount = cpu_to_le16(count);
2595 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2596 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2597 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2599 cFYI(1, "Send error in rename = %d", rc);
2601 cifs_buf_release(pSMB);
2609 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2610 int netfid, const char *target_name,
2611 const struct nls_table *nls_codepage, int remap)
2613 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2614 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2615 struct set_file_rename *rename_info;
2617 char dummy_string[30];
2619 int bytes_returned = 0;
2621 __u16 params, param_offset, offset, count, byte_count;
2623 cFYI(1, "Rename to File by handle");
2624 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2630 pSMB->MaxSetupCount = 0;
2634 pSMB->Reserved2 = 0;
2635 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2636 offset = param_offset + params;
2638 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2639 rename_info = (struct set_file_rename *) data_offset;
2640 pSMB->MaxParameterCount = cpu_to_le16(2);
2641 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2642 pSMB->SetupCount = 1;
2643 pSMB->Reserved3 = 0;
2644 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2645 byte_count = 3 /* pad */ + params;
2646 pSMB->ParameterCount = cpu_to_le16(params);
2647 pSMB->TotalParameterCount = pSMB->ParameterCount;
2648 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2649 pSMB->DataOffset = cpu_to_le16(offset);
2650 /* construct random name ".cifs_tmp<inodenum><mid>" */
2651 rename_info->overwrite = cpu_to_le32(1);
2652 rename_info->root_fid = 0;
2653 /* unicode only call */
2654 if (target_name == NULL) {
2655 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2657 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2658 dummy_string, 24, nls_codepage, remap);
2661 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2662 target_name, PATH_MAX, nls_codepage,
2665 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2666 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2667 byte_count += count;
2668 pSMB->DataCount = cpu_to_le16(count);
2669 pSMB->TotalDataCount = pSMB->DataCount;
2671 pSMB->InformationLevel =
2672 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2673 pSMB->Reserved4 = 0;
2674 inc_rfc1001_len(pSMB, byte_count);
2675 pSMB->ByteCount = cpu_to_le16(byte_count);
2676 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2678 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2680 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2682 cifs_buf_release(pSMB);
2684 /* Note: On -EAGAIN error only caller can retry on handle based calls
2685 since file handle passed in no longer valid */
2691 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2692 const char *fromName, const __u16 target_tid, const char *toName,
2693 const int flags, const struct nls_table *nls_codepage, int remap)
2696 COPY_REQ *pSMB = NULL;
2697 COPY_RSP *pSMBr = NULL;
2699 int name_len, name_len2;
2702 cFYI(1, "In CIFSSMBCopy");
2704 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2709 pSMB->BufferFormat = 0x04;
2710 pSMB->Tid2 = target_tid;
2712 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2714 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2715 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2716 fromName, PATH_MAX, nls_codepage,
2718 name_len++; /* trailing null */
2720 pSMB->OldFileName[name_len] = 0x04; /* pad */
2721 /* protocol requires ASCII signature byte on Unicode string */
2722 pSMB->OldFileName[name_len + 1] = 0x00;
2724 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2725 toName, PATH_MAX, nls_codepage, remap);
2726 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2727 name_len2 *= 2; /* convert to bytes */
2728 } else { /* BB improve the check for buffer overruns BB */
2729 name_len = strnlen(fromName, PATH_MAX);
2730 name_len++; /* trailing null */
2731 strncpy(pSMB->OldFileName, fromName, name_len);
2732 name_len2 = strnlen(toName, PATH_MAX);
2733 name_len2++; /* trailing null */
2734 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2735 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2736 name_len2++; /* trailing null */
2737 name_len2++; /* signature byte */
2740 count = 1 /* 1st signature byte */ + name_len + name_len2;
2741 inc_rfc1001_len(pSMB, count);
2742 pSMB->ByteCount = cpu_to_le16(count);
2744 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2745 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2747 cFYI(1, "Send error in copy = %d with %d files copied",
2748 rc, le16_to_cpu(pSMBr->CopyCount));
2750 cifs_buf_release(pSMB);
2759 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2760 const char *fromName, const char *toName,
2761 const struct nls_table *nls_codepage)
2763 TRANSACTION2_SPI_REQ *pSMB = NULL;
2764 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2767 int name_len_target;
2769 int bytes_returned = 0;
2770 __u16 params, param_offset, offset, byte_count;
2772 cFYI(1, "In Symlink Unix style");
2774 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2779 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2781 cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2782 /* find define for this maxpathcomponent */
2783 PATH_MAX, nls_codepage);
2784 name_len++; /* trailing null */
2787 } else { /* BB improve the check for buffer overruns BB */
2788 name_len = strnlen(fromName, PATH_MAX);
2789 name_len++; /* trailing null */
2790 strncpy(pSMB->FileName, fromName, name_len);
2792 params = 6 + name_len;
2793 pSMB->MaxSetupCount = 0;
2797 pSMB->Reserved2 = 0;
2798 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2799 InformationLevel) - 4;
2800 offset = param_offset + params;
2802 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2803 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2805 cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2806 /* find define for this maxpathcomponent */
2808 name_len_target++; /* trailing null */
2809 name_len_target *= 2;
2810 } else { /* BB improve the check for buffer overruns BB */
2811 name_len_target = strnlen(toName, PATH_MAX);
2812 name_len_target++; /* trailing null */
2813 strncpy(data_offset, toName, name_len_target);
2816 pSMB->MaxParameterCount = cpu_to_le16(2);
2817 /* BB find exact max on data count below from sess */
2818 pSMB->MaxDataCount = cpu_to_le16(1000);
2819 pSMB->SetupCount = 1;
2820 pSMB->Reserved3 = 0;
2821 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2822 byte_count = 3 /* pad */ + params + name_len_target;
2823 pSMB->DataCount = cpu_to_le16(name_len_target);
2824 pSMB->ParameterCount = cpu_to_le16(params);
2825 pSMB->TotalDataCount = pSMB->DataCount;
2826 pSMB->TotalParameterCount = pSMB->ParameterCount;
2827 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2828 pSMB->DataOffset = cpu_to_le16(offset);
2829 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2830 pSMB->Reserved4 = 0;
2831 inc_rfc1001_len(pSMB, byte_count);
2832 pSMB->ByteCount = cpu_to_le16(byte_count);
2833 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2834 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2835 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2837 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2839 cifs_buf_release(pSMB);
2842 goto createSymLinkRetry;
2848 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2849 const char *fromName, const char *toName,
2850 const struct nls_table *nls_codepage, int remap)
2852 TRANSACTION2_SPI_REQ *pSMB = NULL;
2853 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2856 int name_len_target;
2858 int bytes_returned = 0;
2859 __u16 params, param_offset, offset, byte_count;
2861 cFYI(1, "In Create Hard link Unix style");
2862 createHardLinkRetry:
2863 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2868 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2869 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2870 PATH_MAX, nls_codepage, remap);
2871 name_len++; /* trailing null */
2874 } else { /* BB improve the check for buffer overruns BB */
2875 name_len = strnlen(toName, PATH_MAX);
2876 name_len++; /* trailing null */
2877 strncpy(pSMB->FileName, toName, name_len);
2879 params = 6 + name_len;
2880 pSMB->MaxSetupCount = 0;
2884 pSMB->Reserved2 = 0;
2885 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2886 InformationLevel) - 4;
2887 offset = param_offset + params;
2889 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2890 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2892 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2893 PATH_MAX, nls_codepage, remap);
2894 name_len_target++; /* trailing null */
2895 name_len_target *= 2;
2896 } else { /* BB improve the check for buffer overruns BB */
2897 name_len_target = strnlen(fromName, PATH_MAX);
2898 name_len_target++; /* trailing null */
2899 strncpy(data_offset, fromName, name_len_target);
2902 pSMB->MaxParameterCount = cpu_to_le16(2);
2903 /* BB find exact max on data count below from sess*/
2904 pSMB->MaxDataCount = cpu_to_le16(1000);
2905 pSMB->SetupCount = 1;
2906 pSMB->Reserved3 = 0;
2907 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2908 byte_count = 3 /* pad */ + params + name_len_target;
2909 pSMB->ParameterCount = cpu_to_le16(params);
2910 pSMB->TotalParameterCount = pSMB->ParameterCount;
2911 pSMB->DataCount = cpu_to_le16(name_len_target);
2912 pSMB->TotalDataCount = pSMB->DataCount;
2913 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2914 pSMB->DataOffset = cpu_to_le16(offset);
2915 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2916 pSMB->Reserved4 = 0;
2917 inc_rfc1001_len(pSMB, byte_count);
2918 pSMB->ByteCount = cpu_to_le16(byte_count);
2919 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2920 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2921 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2923 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2925 cifs_buf_release(pSMB);
2927 goto createHardLinkRetry;
2933 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2934 const char *from_name, const char *to_name,
2935 struct cifs_sb_info *cifs_sb)
2938 NT_RENAME_REQ *pSMB = NULL;
2939 RENAME_RSP *pSMBr = NULL;
2941 int name_len, name_len2;
2943 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2945 cFYI(1, "In CIFSCreateHardLink");
2946 winCreateHardLinkRetry:
2948 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2953 pSMB->SearchAttributes =
2954 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2956 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2957 pSMB->ClusterCount = 0;
2959 pSMB->BufferFormat = 0x04;
2961 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2963 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2964 PATH_MAX, cifs_sb->local_nls, remap);
2965 name_len++; /* trailing null */
2968 /* protocol specifies ASCII buffer format (0x04) for unicode */
2969 pSMB->OldFileName[name_len] = 0x04;
2970 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2972 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2973 to_name, PATH_MAX, cifs_sb->local_nls,
2975 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2976 name_len2 *= 2; /* convert to bytes */
2977 } else { /* BB improve the check for buffer overruns BB */
2978 name_len = strnlen(from_name, PATH_MAX);
2979 name_len++; /* trailing null */
2980 strncpy(pSMB->OldFileName, from_name, name_len);
2981 name_len2 = strnlen(to_name, PATH_MAX);
2982 name_len2++; /* trailing null */
2983 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2984 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2985 name_len2++; /* trailing null */
2986 name_len2++; /* signature byte */
2989 count = 1 /* string type byte */ + name_len + name_len2;
2990 inc_rfc1001_len(pSMB, count);
2991 pSMB->ByteCount = cpu_to_le16(count);
2993 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2994 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2995 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2997 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2999 cifs_buf_release(pSMB);
3001 goto winCreateHardLinkRetry;
3007 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3008 const unsigned char *searchName, char **symlinkinfo,
3009 const struct nls_table *nls_codepage)
3011 /* SMB_QUERY_FILE_UNIX_LINK */
3012 TRANSACTION2_QPI_REQ *pSMB = NULL;
3013 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3017 __u16 params, byte_count;
3020 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3023 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3028 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3030 cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3031 PATH_MAX, nls_codepage);
3032 name_len++; /* trailing null */
3034 } else { /* BB improve the check for buffer overruns BB */
3035 name_len = strnlen(searchName, PATH_MAX);
3036 name_len++; /* trailing null */
3037 strncpy(pSMB->FileName, searchName, name_len);
3040 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3041 pSMB->TotalDataCount = 0;
3042 pSMB->MaxParameterCount = cpu_to_le16(2);
3043 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3044 pSMB->MaxSetupCount = 0;
3048 pSMB->Reserved2 = 0;
3049 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3050 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3051 pSMB->DataCount = 0;
3052 pSMB->DataOffset = 0;
3053 pSMB->SetupCount = 1;
3054 pSMB->Reserved3 = 0;
3055 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3056 byte_count = params + 1 /* pad */ ;
3057 pSMB->TotalParameterCount = cpu_to_le16(params);
3058 pSMB->ParameterCount = pSMB->TotalParameterCount;
3059 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3060 pSMB->Reserved4 = 0;
3061 inc_rfc1001_len(pSMB, byte_count);
3062 pSMB->ByteCount = cpu_to_le16(byte_count);
3064 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3065 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3067 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3069 /* decode response */
3071 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3072 /* BB also check enough total bytes returned */
3073 if (rc || get_bcc(&pSMBr->hdr) < 2)
3077 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3079 data_start = ((char *) &pSMBr->hdr.Protocol) +
3080 le16_to_cpu(pSMBr->t2.DataOffset);
3082 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3087 /* BB FIXME investigate remapping reserved chars here */
3088 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3089 count, is_unicode, nls_codepage);
3094 cifs_buf_release(pSMB);
3096 goto querySymLinkRetry;
3100 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3102 * Recent Windows versions now create symlinks more frequently
3103 * and they use the "reparse point" mechanism below. We can of course
3104 * do symlinks nicely to Samba and other servers which support the
3105 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3106 * "MF" symlinks optionally, but for recent Windows we really need to
3107 * reenable the code below and fix the cifs_symlink callers to handle this.
3108 * In the interim this code has been moved to its own config option so
3109 * it is not compiled in by default until callers fixed up and more tested.
3112 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3113 const unsigned char *searchName,
3114 char *symlinkinfo, const int buflen, __u16 fid,
3115 const struct nls_table *nls_codepage)
3119 struct smb_com_transaction_ioctl_req *pSMB;
3120 struct smb_com_transaction_ioctl_rsp *pSMBr;
3122 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3123 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3128 pSMB->TotalParameterCount = 0 ;
3129 pSMB->TotalDataCount = 0;
3130 pSMB->MaxParameterCount = cpu_to_le32(2);
3131 /* BB find exact data count max from sess structure BB */
3132 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3133 pSMB->MaxSetupCount = 4;
3135 pSMB->ParameterOffset = 0;
3136 pSMB->DataCount = 0;
3137 pSMB->DataOffset = 0;
3138 pSMB->SetupCount = 4;
3139 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3140 pSMB->ParameterCount = pSMB->TotalParameterCount;
3141 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3142 pSMB->IsFsctl = 1; /* FSCTL */
3143 pSMB->IsRootFlag = 0;
3144 pSMB->Fid = fid; /* file handle always le */
3145 pSMB->ByteCount = 0;
3147 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3148 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3150 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3151 } else { /* decode response */
3152 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3153 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3154 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3155 /* BB also check enough total bytes returned */
3156 rc = -EIO; /* bad smb */
3159 if (data_count && (data_count < 2048)) {
3160 char *end_of_smb = 2 /* sizeof byte count */ +
3161 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3163 struct reparse_data *reparse_buf =
3164 (struct reparse_data *)
3165 ((char *)&pSMBr->hdr.Protocol
3167 if ((char *)reparse_buf >= end_of_smb) {
3171 if ((reparse_buf->LinkNamesBuf +
3172 reparse_buf->TargetNameOffset +
3173 reparse_buf->TargetNameLen) > end_of_smb) {
3174 cFYI(1, "reparse buf beyond SMB");
3179 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3180 cifs_from_ucs2(symlinkinfo, (__le16 *)
3181 (reparse_buf->LinkNamesBuf +
3182 reparse_buf->TargetNameOffset),
3184 reparse_buf->TargetNameLen,
3186 } else { /* ASCII names */
3187 strncpy(symlinkinfo,
3188 reparse_buf->LinkNamesBuf +
3189 reparse_buf->TargetNameOffset,
3190 min_t(const int, buflen,
3191 reparse_buf->TargetNameLen));
3195 cFYI(1, "Invalid return data count on "
3196 "get reparse info ioctl");
3198 symlinkinfo[buflen] = 0; /* just in case so the caller
3199 does not go off the end of the buffer */
3200 cFYI(1, "readlink result - %s", symlinkinfo);
3204 cifs_buf_release(pSMB);
3206 /* Note: On -EAGAIN error only caller can retry on handle based calls
3207 since file handle passed in no longer valid */
3211 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3213 #ifdef CONFIG_CIFS_POSIX
3215 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3216 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3217 struct cifs_posix_ace *cifs_ace)
3219 /* u8 cifs fields do not need le conversion */
3220 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3221 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3222 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3223 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3228 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3229 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3230 const int acl_type, const int size_of_data_area)
3235 struct cifs_posix_ace *pACE;
3236 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3237 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3239 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3242 if (acl_type & ACL_TYPE_ACCESS) {
3243 count = le16_to_cpu(cifs_acl->access_entry_count);
3244 pACE = &cifs_acl->ace_array[0];
3245 size = sizeof(struct cifs_posix_acl);
3246 size += sizeof(struct cifs_posix_ace) * count;
3247 /* check if we would go beyond end of SMB */
3248 if (size_of_data_area < size) {
3249 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3250 size_of_data_area, size);
3253 } else if (acl_type & ACL_TYPE_DEFAULT) {
3254 count = le16_to_cpu(cifs_acl->access_entry_count);
3255 size = sizeof(struct cifs_posix_acl);
3256 size += sizeof(struct cifs_posix_ace) * count;
3257 /* skip past access ACEs to get to default ACEs */
3258 pACE = &cifs_acl->ace_array[count];
3259 count = le16_to_cpu(cifs_acl->default_entry_count);
3260 size += sizeof(struct cifs_posix_ace) * count;
3261 /* check if we would go beyond end of SMB */
3262 if (size_of_data_area < size)
3269 size = posix_acl_xattr_size(count);
3270 if ((buflen == 0) || (local_acl == NULL)) {
3271 /* used to query ACL EA size */
3272 } else if (size > buflen) {
3274 } else /* buffer big enough */ {
3275 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3276 for (i = 0; i < count ; i++) {
3277 cifs_convert_ace(&local_acl->a_entries[i], pACE);
3284 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3285 const posix_acl_xattr_entry *local_ace)
3287 __u16 rc = 0; /* 0 = ACL converted ok */
3289 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3290 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3291 /* BB is there a better way to handle the large uid? */
3292 if (local_ace->e_id == cpu_to_le32(-1)) {
3293 /* Probably no need to le convert -1 on any arch but can not hurt */
3294 cifs_ace->cifs_uid = cpu_to_le64(-1);
3296 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3297 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3301 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3302 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3303 const int buflen, const int acl_type)
3306 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3307 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3311 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3314 count = posix_acl_xattr_count((size_t)buflen);
3315 cFYI(1, "setting acl with %d entries from buf of length %d and "
3317 count, buflen, le32_to_cpu(local_acl->a_version));
3318 if (le32_to_cpu(local_acl->a_version) != 2) {
3319 cFYI(1, "unknown POSIX ACL version %d",
3320 le32_to_cpu(local_acl->a_version));
3323 cifs_acl->version = cpu_to_le16(1);
3324 if (acl_type == ACL_TYPE_ACCESS)
3325 cifs_acl->access_entry_count = cpu_to_le16(count);
3326 else if (acl_type == ACL_TYPE_DEFAULT)
3327 cifs_acl->default_entry_count = cpu_to_le16(count);
3329 cFYI(1, "unknown ACL type %d", acl_type);
3332 for (i = 0; i < count; i++) {
3333 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3334 &local_acl->a_entries[i]);
3336 /* ACE not converted */
3341 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3342 rc += sizeof(struct cifs_posix_acl);
3343 /* BB add check to make sure ACL does not overflow SMB */
3349 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3350 const unsigned char *searchName,
3351 char *acl_inf, const int buflen, const int acl_type,
3352 const struct nls_table *nls_codepage, int remap)
3354 /* SMB_QUERY_POSIX_ACL */
3355 TRANSACTION2_QPI_REQ *pSMB = NULL;
3356 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3360 __u16 params, byte_count;
3362 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3365 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3372 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3373 searchName, PATH_MAX, nls_codepage,
3375 name_len++; /* trailing null */
3377 pSMB->FileName[name_len] = 0;
3378 pSMB->FileName[name_len+1] = 0;
3379 } else { /* BB improve the check for buffer overruns BB */
3380 name_len = strnlen(searchName, PATH_MAX);
3381 name_len++; /* trailing null */
3382 strncpy(pSMB->FileName, searchName, name_len);
3385 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3386 pSMB->TotalDataCount = 0;
3387 pSMB->MaxParameterCount = cpu_to_le16(2);
3388 /* BB find exact max data count below from sess structure BB */
3389 pSMB->MaxDataCount = cpu_to_le16(4000);
3390 pSMB->MaxSetupCount = 0;
3394 pSMB->Reserved2 = 0;
3395 pSMB->ParameterOffset = cpu_to_le16(
3396 offsetof(struct smb_com_transaction2_qpi_req,
3397 InformationLevel) - 4);
3398 pSMB->DataCount = 0;
3399 pSMB->DataOffset = 0;
3400 pSMB->SetupCount = 1;
3401 pSMB->Reserved3 = 0;
3402 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3403 byte_count = params + 1 /* pad */ ;
3404 pSMB->TotalParameterCount = cpu_to_le16(params);
3405 pSMB->ParameterCount = pSMB->TotalParameterCount;
3406 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3407 pSMB->Reserved4 = 0;
3408 inc_rfc1001_len(pSMB, byte_count);
3409 pSMB->ByteCount = cpu_to_le16(byte_count);
3411 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3412 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3413 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3415 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3417 /* decode response */
3419 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3420 /* BB also check enough total bytes returned */
3421 if (rc || get_bcc(&pSMBr->hdr) < 2)
3422 rc = -EIO; /* bad smb */
3424 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3425 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3426 rc = cifs_copy_posix_acl(acl_inf,
3427 (char *)&pSMBr->hdr.Protocol+data_offset,
3428 buflen, acl_type, count);
3431 cifs_buf_release(pSMB);
3438 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3439 const unsigned char *fileName,
3440 const char *local_acl, const int buflen,
3442 const struct nls_table *nls_codepage, int remap)
3444 struct smb_com_transaction2_spi_req *pSMB = NULL;
3445 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3449 int bytes_returned = 0;
3450 __u16 params, byte_count, data_count, param_offset, offset;
3452 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3454 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3458 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3460 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3461 PATH_MAX, nls_codepage, remap);
3462 name_len++; /* trailing null */
3464 } else { /* BB improve the check for buffer overruns BB */
3465 name_len = strnlen(fileName, PATH_MAX);
3466 name_len++; /* trailing null */
3467 strncpy(pSMB->FileName, fileName, name_len);
3469 params = 6 + name_len;
3470 pSMB->MaxParameterCount = cpu_to_le16(2);
3471 /* BB find max SMB size from sess */
3472 pSMB->MaxDataCount = cpu_to_le16(1000);
3473 pSMB->MaxSetupCount = 0;
3477 pSMB->Reserved2 = 0;
3478 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3479 InformationLevel) - 4;
3480 offset = param_offset + params;
3481 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3482 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3484 /* convert to on the wire format for POSIX ACL */
3485 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3487 if (data_count == 0) {
3489 goto setACLerrorExit;
3491 pSMB->DataOffset = cpu_to_le16(offset);
3492 pSMB->SetupCount = 1;
3493 pSMB->Reserved3 = 0;
3494 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3495 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3496 byte_count = 3 /* pad */ + params + data_count;
3497 pSMB->DataCount = cpu_to_le16(data_count);
3498 pSMB->TotalDataCount = pSMB->DataCount;
3499 pSMB->ParameterCount = cpu_to_le16(params);
3500 pSMB->TotalParameterCount = pSMB->ParameterCount;
3501 pSMB->Reserved4 = 0;
3502 inc_rfc1001_len(pSMB, byte_count);
3503 pSMB->ByteCount = cpu_to_le16(byte_count);
3504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3507 cFYI(1, "Set POSIX ACL returned %d", rc);
3510 cifs_buf_release(pSMB);
3516 /* BB fix tabs in this function FIXME BB */
3518 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3519 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3522 struct smb_t2_qfi_req *pSMB = NULL;
3523 struct smb_t2_qfi_rsp *pSMBr = NULL;
3525 __u16 params, byte_count;
3527 cFYI(1, "In GetExtAttr");
3532 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3537 params = 2 /* level */ + 2 /* fid */;
3538 pSMB->t2.TotalDataCount = 0;
3539 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3540 /* BB find exact max data count below from sess structure BB */
3541 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3542 pSMB->t2.MaxSetupCount = 0;
3543 pSMB->t2.Reserved = 0;
3545 pSMB->t2.Timeout = 0;
3546 pSMB->t2.Reserved2 = 0;
3547 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3549 pSMB->t2.DataCount = 0;
3550 pSMB->t2.DataOffset = 0;
3551 pSMB->t2.SetupCount = 1;
3552 pSMB->t2.Reserved3 = 0;
3553 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3554 byte_count = params + 1 /* pad */ ;
3555 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3556 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3557 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3560 inc_rfc1001_len(pSMB, byte_count);
3561 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3563 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3564 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3566 cFYI(1, "error %d in GetExtAttr", rc);
3568 /* decode response */
3569 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3570 /* BB also check enough total bytes returned */
3571 if (rc || get_bcc(&pSMBr->hdr) < 2)
3572 /* If rc should we check for EOPNOSUPP and
3573 disable the srvino flag? or in caller? */
3574 rc = -EIO; /* bad smb */
3576 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3577 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3578 struct file_chattr_info *pfinfo;
3579 /* BB Do we need a cast or hash here ? */
3581 cFYI(1, "Illegal size ret in GetExtAttr");
3585 pfinfo = (struct file_chattr_info *)
3586 (data_offset + (char *) &pSMBr->hdr.Protocol);
3587 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3588 *pMask = le64_to_cpu(pfinfo->mask);
3592 cifs_buf_release(pSMB);
3594 goto GetExtAttrRetry;
3598 #endif /* CONFIG_POSIX */
3600 #ifdef CONFIG_CIFS_ACL
3602 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3603 * all NT TRANSACTS that we init here have total parm and data under about 400
3604 * bytes (to fit in small cifs buffer size), which is the case so far, it
3605 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3606 * returned setup area) and MaxParameterCount (returned parms size) must be set
3610 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3611 const int parm_len, struct cifs_tcon *tcon,
3616 struct smb_com_ntransact_req *pSMB;
3618 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3622 *ret_buf = (void *)pSMB;
3624 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3625 pSMB->TotalDataCount = 0;
3626 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3627 pSMB->ParameterCount = pSMB->TotalParameterCount;
3628 pSMB->DataCount = pSMB->TotalDataCount;
3629 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3630 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3631 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3632 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3633 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3634 pSMB->SubCommand = cpu_to_le16(sub_command);
3639 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3640 __u32 *pparmlen, __u32 *pdatalen)
3643 __u32 data_count, data_offset, parm_count, parm_offset;
3644 struct smb_com_ntransact_rsp *pSMBr;
3653 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3655 bcc = get_bcc(&pSMBr->hdr);
3656 end_of_smb = 2 /* sizeof byte count */ + bcc +
3657 (char *)&pSMBr->ByteCount;
3659 data_offset = le32_to_cpu(pSMBr->DataOffset);
3660 data_count = le32_to_cpu(pSMBr->DataCount);
3661 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3662 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3664 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3665 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3667 /* should we also check that parm and data areas do not overlap? */
3668 if (*ppparm > end_of_smb) {
3669 cFYI(1, "parms start after end of smb");
3671 } else if (parm_count + *ppparm > end_of_smb) {
3672 cFYI(1, "parm end after end of smb");
3674 } else if (*ppdata > end_of_smb) {
3675 cFYI(1, "data starts after end of smb");
3677 } else if (data_count + *ppdata > end_of_smb) {
3678 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3679 *ppdata, data_count, (data_count + *ppdata),
3682 } else if (parm_count + data_count > bcc) {
3683 cFYI(1, "parm count and data count larger than SMB");
3686 *pdatalen = data_count;
3687 *pparmlen = parm_count;
3691 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3693 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3694 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3698 QUERY_SEC_DESC_REQ *pSMB;
3701 cFYI(1, "GetCifsACL");
3706 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3707 8 /* parm len */, tcon, (void **) &pSMB);
3711 pSMB->MaxParameterCount = cpu_to_le32(4);
3712 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3713 pSMB->MaxSetupCount = 0;
3714 pSMB->Fid = fid; /* file handle always le */
3715 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3717 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3718 inc_rfc1001_len(pSMB, 11);
3719 iov[0].iov_base = (char *)pSMB;
3720 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3722 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3724 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3726 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3727 } else { /* decode response */
3731 struct smb_com_ntransact_rsp *pSMBr;
3734 /* validate_nttransact */
3735 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3736 &pdata, &parm_len, pbuflen);
3739 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3741 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3743 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3744 rc = -EIO; /* bad smb */
3749 /* BB check that data area is minimum length and as big as acl_len */
3751 acl_len = le32_to_cpu(*parm);
3752 if (acl_len != *pbuflen) {
3753 cERROR(1, "acl length %d does not match %d",
3755 if (*pbuflen > acl_len)
3759 /* check if buffer is big enough for the acl
3760 header followed by the smallest SID */
3761 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3762 (*pbuflen >= 64 * 1024)) {
3763 cERROR(1, "bad acl length %d", *pbuflen);
3767 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3768 if (*acl_inf == NULL) {
3772 memcpy(*acl_inf, pdata, *pbuflen);
3776 if (buf_type == CIFS_SMALL_BUFFER)
3777 cifs_small_buf_release(iov[0].iov_base);
3778 else if (buf_type == CIFS_LARGE_BUFFER)
3779 cifs_buf_release(iov[0].iov_base);
3780 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3785 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3786 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3788 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3790 int bytes_returned = 0;
3791 SET_SEC_DESC_REQ *pSMB = NULL;
3795 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3799 pSMB->MaxSetupCount = 0;
3803 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3804 data_count = acllen;
3805 data_offset = param_offset + param_count;
3806 byte_count = 3 /* pad */ + param_count;
3808 pSMB->DataCount = cpu_to_le32(data_count);
3809 pSMB->TotalDataCount = pSMB->DataCount;
3810 pSMB->MaxParameterCount = cpu_to_le32(4);
3811 pSMB->MaxDataCount = cpu_to_le32(16384);
3812 pSMB->ParameterCount = cpu_to_le32(param_count);
3813 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3814 pSMB->TotalParameterCount = pSMB->ParameterCount;
3815 pSMB->DataOffset = cpu_to_le32(data_offset);
3816 pSMB->SetupCount = 0;
3817 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3818 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3820 pSMB->Fid = fid; /* file handle always le */
3821 pSMB->Reserved2 = 0;
3822 pSMB->AclFlags = cpu_to_le32(aclflag);
3824 if (pntsd && acllen) {
3825 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3826 data_offset, pntsd, acllen);
3827 inc_rfc1001_len(pSMB, byte_count + data_count);
3829 inc_rfc1001_len(pSMB, byte_count);
3831 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3832 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3834 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3836 cFYI(1, "Set CIFS ACL returned %d", rc);
3837 cifs_buf_release(pSMB);
3840 goto setCifsAclRetry;
3845 #endif /* CONFIG_CIFS_ACL */
3847 /* Legacy Query Path Information call for lookup to old servers such
3850 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3851 const char *search_name, FILE_ALL_INFO *data,
3852 const struct nls_table *nls_codepage, int remap)
3854 QUERY_INFORMATION_REQ *pSMB;
3855 QUERY_INFORMATION_RSP *pSMBr;
3860 cFYI(1, "In SMBQPath path %s", search_name);
3862 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3867 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3869 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3870 search_name, PATH_MAX, nls_codepage,
3872 name_len++; /* trailing null */
3875 name_len = strnlen(search_name, PATH_MAX);
3876 name_len++; /* trailing null */
3877 strncpy(pSMB->FileName, search_name, name_len);
3879 pSMB->BufferFormat = 0x04;
3880 name_len++; /* account for buffer type byte */
3881 inc_rfc1001_len(pSMB, (__u16)name_len);
3882 pSMB->ByteCount = cpu_to_le16(name_len);
3884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3887 cFYI(1, "Send error in QueryInfo = %d", rc);
3890 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3892 /* decode response */
3893 /* BB FIXME - add time zone adjustment BB */
3894 memset(data, 0, sizeof(FILE_ALL_INFO));
3897 /* decode time fields */
3898 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3899 data->LastWriteTime = data->ChangeTime;
3900 data->LastAccessTime = 0;
3901 data->AllocationSize =
3902 cpu_to_le64(le32_to_cpu(pSMBr->size));
3903 data->EndOfFile = data->AllocationSize;
3905 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3907 rc = -EIO; /* bad buffer passed in */
3909 cifs_buf_release(pSMB);
3918 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3919 u16 netfid, FILE_ALL_INFO *pFindData)
3921 struct smb_t2_qfi_req *pSMB = NULL;
3922 struct smb_t2_qfi_rsp *pSMBr = NULL;
3925 __u16 params, byte_count;
3928 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3933 params = 2 /* level */ + 2 /* fid */;
3934 pSMB->t2.TotalDataCount = 0;
3935 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3936 /* BB find exact max data count below from sess structure BB */
3937 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3938 pSMB->t2.MaxSetupCount = 0;
3939 pSMB->t2.Reserved = 0;
3941 pSMB->t2.Timeout = 0;
3942 pSMB->t2.Reserved2 = 0;
3943 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3945 pSMB->t2.DataCount = 0;
3946 pSMB->t2.DataOffset = 0;
3947 pSMB->t2.SetupCount = 1;
3948 pSMB->t2.Reserved3 = 0;
3949 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3950 byte_count = params + 1 /* pad */ ;
3951 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3952 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3953 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3956 inc_rfc1001_len(pSMB, byte_count);
3958 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3959 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3961 cFYI(1, "Send error in QPathInfo = %d", rc);
3962 } else { /* decode response */
3963 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3965 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3967 else if (get_bcc(&pSMBr->hdr) < 40)
3968 rc = -EIO; /* bad smb */
3969 else if (pFindData) {
3970 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3971 memcpy((char *) pFindData,
3972 (char *) &pSMBr->hdr.Protocol +
3973 data_offset, sizeof(FILE_ALL_INFO));
3977 cifs_buf_release(pSMB);
3979 goto QFileInfoRetry;
3985 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3986 const char *search_name, FILE_ALL_INFO *data,
3987 int legacy /* old style infolevel */,
3988 const struct nls_table *nls_codepage, int remap)
3990 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3991 TRANSACTION2_QPI_REQ *pSMB = NULL;
3992 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3996 __u16 params, byte_count;
3998 /* cFYI(1, "In QPathInfo path %s", search_name); */
4000 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4005 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4007 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4008 PATH_MAX, nls_codepage, remap);
4009 name_len++; /* trailing null */
4011 } else { /* BB improve the check for buffer overruns BB */
4012 name_len = strnlen(search_name, PATH_MAX);
4013 name_len++; /* trailing null */
4014 strncpy(pSMB->FileName, search_name, name_len);
4017 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4018 pSMB->TotalDataCount = 0;
4019 pSMB->MaxParameterCount = cpu_to_le16(2);
4020 /* BB find exact max SMB PDU from sess structure BB */
4021 pSMB->MaxDataCount = cpu_to_le16(4000);
4022 pSMB->MaxSetupCount = 0;
4026 pSMB->Reserved2 = 0;
4027 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4028 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4029 pSMB->DataCount = 0;
4030 pSMB->DataOffset = 0;
4031 pSMB->SetupCount = 1;
4032 pSMB->Reserved3 = 0;
4033 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4034 byte_count = params + 1 /* pad */ ;
4035 pSMB->TotalParameterCount = cpu_to_le16(params);
4036 pSMB->ParameterCount = pSMB->TotalParameterCount;
4038 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4040 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4041 pSMB->Reserved4 = 0;
4042 inc_rfc1001_len(pSMB, byte_count);
4043 pSMB->ByteCount = cpu_to_le16(byte_count);
4045 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4046 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4048 cFYI(1, "Send error in QPathInfo = %d", rc);
4049 } else { /* decode response */
4050 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4052 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4054 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4055 rc = -EIO; /* bad smb */
4056 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4057 rc = -EIO; /* 24 or 26 expected but we do not read
4061 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4064 * On legacy responses we do not read the last field,
4065 * EAsize, fortunately since it varies by subdialect and
4066 * also note it differs on Set vs Get, ie two bytes or 4
4067 * bytes depending but we don't care here.
4070 size = sizeof(FILE_INFO_STANDARD);
4072 size = sizeof(FILE_ALL_INFO);
4073 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4078 cifs_buf_release(pSMB);
4080 goto QPathInfoRetry;
4086 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4087 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4089 struct smb_t2_qfi_req *pSMB = NULL;
4090 struct smb_t2_qfi_rsp *pSMBr = NULL;
4093 __u16 params, byte_count;
4096 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4101 params = 2 /* level */ + 2 /* fid */;
4102 pSMB->t2.TotalDataCount = 0;
4103 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4104 /* BB find exact max data count below from sess structure BB */
4105 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4106 pSMB->t2.MaxSetupCount = 0;
4107 pSMB->t2.Reserved = 0;
4109 pSMB->t2.Timeout = 0;
4110 pSMB->t2.Reserved2 = 0;
4111 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4113 pSMB->t2.DataCount = 0;
4114 pSMB->t2.DataOffset = 0;
4115 pSMB->t2.SetupCount = 1;
4116 pSMB->t2.Reserved3 = 0;
4117 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4118 byte_count = params + 1 /* pad */ ;
4119 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4120 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4121 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4124 inc_rfc1001_len(pSMB, byte_count);
4126 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4127 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4129 cFYI(1, "Send error in QPathInfo = %d", rc);
4130 } else { /* decode response */
4131 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4133 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4134 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4135 "Unix Extensions can be disabled on mount "
4136 "by specifying the nosfu mount option.");
4137 rc = -EIO; /* bad smb */
4139 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4140 memcpy((char *) pFindData,
4141 (char *) &pSMBr->hdr.Protocol +
4143 sizeof(FILE_UNIX_BASIC_INFO));
4147 cifs_buf_release(pSMB);
4149 goto UnixQFileInfoRetry;
4155 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4156 const unsigned char *searchName,
4157 FILE_UNIX_BASIC_INFO *pFindData,
4158 const struct nls_table *nls_codepage, int remap)
4160 /* SMB_QUERY_FILE_UNIX_BASIC */
4161 TRANSACTION2_QPI_REQ *pSMB = NULL;
4162 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4164 int bytes_returned = 0;
4166 __u16 params, byte_count;
4168 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4170 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4175 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4177 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4178 PATH_MAX, nls_codepage, remap);
4179 name_len++; /* trailing null */
4181 } else { /* BB improve the check for buffer overruns BB */
4182 name_len = strnlen(searchName, PATH_MAX);
4183 name_len++; /* trailing null */
4184 strncpy(pSMB->FileName, searchName, name_len);
4187 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4188 pSMB->TotalDataCount = 0;
4189 pSMB->MaxParameterCount = cpu_to_le16(2);
4190 /* BB find exact max SMB PDU from sess structure BB */
4191 pSMB->MaxDataCount = cpu_to_le16(4000);
4192 pSMB->MaxSetupCount = 0;
4196 pSMB->Reserved2 = 0;
4197 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4198 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4199 pSMB->DataCount = 0;
4200 pSMB->DataOffset = 0;
4201 pSMB->SetupCount = 1;
4202 pSMB->Reserved3 = 0;
4203 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4204 byte_count = params + 1 /* pad */ ;
4205 pSMB->TotalParameterCount = cpu_to_le16(params);
4206 pSMB->ParameterCount = pSMB->TotalParameterCount;
4207 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4208 pSMB->Reserved4 = 0;
4209 inc_rfc1001_len(pSMB, byte_count);
4210 pSMB->ByteCount = cpu_to_le16(byte_count);
4212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4215 cFYI(1, "Send error in QPathInfo = %d", rc);
4216 } else { /* decode response */
4217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4219 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4220 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4221 "Unix Extensions can be disabled on mount "
4222 "by specifying the nosfu mount option.");
4223 rc = -EIO; /* bad smb */
4225 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4226 memcpy((char *) pFindData,
4227 (char *) &pSMBr->hdr.Protocol +
4229 sizeof(FILE_UNIX_BASIC_INFO));
4232 cifs_buf_release(pSMB);
4234 goto UnixQPathInfoRetry;
4239 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4241 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4242 const char *searchName,
4243 const struct nls_table *nls_codepage,
4244 __u16 *pnetfid, __u16 search_flags,
4245 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4247 /* level 257 SMB_ */
4248 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4249 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4250 T2_FFIRST_RSP_PARMS *parms;
4252 int bytes_returned = 0;
4254 __u16 params, byte_count;
4256 cFYI(1, "In FindFirst for %s", searchName);
4259 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4264 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4266 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4267 PATH_MAX, nls_codepage, remap);
4268 /* We can not add the asterik earlier in case
4269 it got remapped to 0xF03A as if it were part of the
4270 directory name instead of a wildcard */
4272 pSMB->FileName[name_len] = dirsep;
4273 pSMB->FileName[name_len+1] = 0;
4274 pSMB->FileName[name_len+2] = '*';
4275 pSMB->FileName[name_len+3] = 0;
4276 name_len += 4; /* now the trailing null */
4277 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4278 pSMB->FileName[name_len+1] = 0;
4280 } else { /* BB add check for overrun of SMB buf BB */
4281 name_len = strnlen(searchName, PATH_MAX);
4282 /* BB fix here and in unicode clause above ie
4283 if (name_len > buffersize-header)
4284 free buffer exit; BB */
4285 strncpy(pSMB->FileName, searchName, name_len);
4286 pSMB->FileName[name_len] = dirsep;
4287 pSMB->FileName[name_len+1] = '*';
4288 pSMB->FileName[name_len+2] = 0;
4292 params = 12 + name_len /* includes null */ ;
4293 pSMB->TotalDataCount = 0; /* no EAs */
4294 pSMB->MaxParameterCount = cpu_to_le16(10);
4295 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4296 pSMB->MaxSetupCount = 0;
4300 pSMB->Reserved2 = 0;
4301 byte_count = params + 1 /* pad */ ;
4302 pSMB->TotalParameterCount = cpu_to_le16(params);
4303 pSMB->ParameterCount = pSMB->TotalParameterCount;
4304 pSMB->ParameterOffset = cpu_to_le16(
4305 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4307 pSMB->DataCount = 0;
4308 pSMB->DataOffset = 0;
4309 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4310 pSMB->Reserved3 = 0;
4311 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4312 pSMB->SearchAttributes =
4313 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4315 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4316 pSMB->SearchFlags = cpu_to_le16(search_flags);
4317 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4319 /* BB what should we set StorageType to? Does it matter? BB */
4320 pSMB->SearchStorageType = 0;
4321 inc_rfc1001_len(pSMB, byte_count);
4322 pSMB->ByteCount = cpu_to_le16(byte_count);
4324 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4325 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4326 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4328 if (rc) {/* BB add logic to retry regular search if Unix search
4329 rejected unexpectedly by server */
4330 /* BB Add code to handle unsupported level rc */
4331 cFYI(1, "Error in FindFirst = %d", rc);
4333 cifs_buf_release(pSMB);
4335 /* BB eventually could optimize out free and realloc of buf */
4338 goto findFirstRetry;
4339 } else { /* decode response */
4340 /* BB remember to free buffer if error BB */
4341 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4345 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4346 psrch_inf->unicode = true;
4348 psrch_inf->unicode = false;
4350 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4351 psrch_inf->smallBuf = 0;
4352 psrch_inf->srch_entries_start =
4353 (char *) &pSMBr->hdr.Protocol +
4354 le16_to_cpu(pSMBr->t2.DataOffset);
4355 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4356 le16_to_cpu(pSMBr->t2.ParameterOffset));
4358 if (parms->EndofSearch)
4359 psrch_inf->endOfSearch = true;
4361 psrch_inf->endOfSearch = false;
4363 psrch_inf->entries_in_buffer =
4364 le16_to_cpu(parms->SearchCount);
4365 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4366 psrch_inf->entries_in_buffer;
4367 lnoff = le16_to_cpu(parms->LastNameOffset);
4368 if (CIFSMaxBufSize < lnoff) {
4369 cERROR(1, "ignoring corrupt resume name");
4370 psrch_inf->last_entry = NULL;
4374 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4377 *pnetfid = parms->SearchHandle;
4379 cifs_buf_release(pSMB);
4386 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4387 __u16 searchHandle, __u16 search_flags,
4388 struct cifs_search_info *psrch_inf)
4390 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4391 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4392 T2_FNEXT_RSP_PARMS *parms;
4393 char *response_data;
4396 unsigned int name_len;
4397 __u16 params, byte_count;
4399 cFYI(1, "In FindNext");
4401 if (psrch_inf->endOfSearch)
4404 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4409 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4411 pSMB->TotalDataCount = 0; /* no EAs */
4412 pSMB->MaxParameterCount = cpu_to_le16(8);
4413 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4414 pSMB->MaxSetupCount = 0;
4418 pSMB->Reserved2 = 0;
4419 pSMB->ParameterOffset = cpu_to_le16(
4420 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4421 pSMB->DataCount = 0;
4422 pSMB->DataOffset = 0;
4423 pSMB->SetupCount = 1;
4424 pSMB->Reserved3 = 0;
4425 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4426 pSMB->SearchHandle = searchHandle; /* always kept as le */
4428 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4429 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4430 pSMB->ResumeKey = psrch_inf->resume_key;
4431 pSMB->SearchFlags = cpu_to_le16(search_flags);
4433 name_len = psrch_inf->resume_name_len;
4435 if (name_len < PATH_MAX) {
4436 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4437 byte_count += name_len;
4438 /* 14 byte parm len above enough for 2 byte null terminator */
4439 pSMB->ResumeFileName[name_len] = 0;
4440 pSMB->ResumeFileName[name_len+1] = 0;
4443 goto FNext2_err_exit;
4445 byte_count = params + 1 /* pad */ ;
4446 pSMB->TotalParameterCount = cpu_to_le16(params);
4447 pSMB->ParameterCount = pSMB->TotalParameterCount;
4448 inc_rfc1001_len(pSMB, byte_count);
4449 pSMB->ByteCount = cpu_to_le16(byte_count);
4451 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4452 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4453 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4456 psrch_inf->endOfSearch = true;
4457 cifs_buf_release(pSMB);
4458 rc = 0; /* search probably was closed at end of search*/
4460 cFYI(1, "FindNext returned = %d", rc);
4461 } else { /* decode response */
4462 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4467 /* BB fixme add lock for file (srch_info) struct here */
4468 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4469 psrch_inf->unicode = true;
4471 psrch_inf->unicode = false;
4472 response_data = (char *) &pSMBr->hdr.Protocol +
4473 le16_to_cpu(pSMBr->t2.ParameterOffset);
4474 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4475 response_data = (char *)&pSMBr->hdr.Protocol +
4476 le16_to_cpu(pSMBr->t2.DataOffset);
4477 if (psrch_inf->smallBuf)
4478 cifs_small_buf_release(
4479 psrch_inf->ntwrk_buf_start);
4481 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4482 psrch_inf->srch_entries_start = response_data;
4483 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4484 psrch_inf->smallBuf = 0;
4485 if (parms->EndofSearch)
4486 psrch_inf->endOfSearch = true;
4488 psrch_inf->endOfSearch = false;
4489 psrch_inf->entries_in_buffer =
4490 le16_to_cpu(parms->SearchCount);
4491 psrch_inf->index_of_last_entry +=
4492 psrch_inf->entries_in_buffer;
4493 lnoff = le16_to_cpu(parms->LastNameOffset);
4494 if (CIFSMaxBufSize < lnoff) {
4495 cERROR(1, "ignoring corrupt resume name");
4496 psrch_inf->last_entry = NULL;
4499 psrch_inf->last_entry =
4500 psrch_inf->srch_entries_start + lnoff;
4502 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4503 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4505 /* BB fixme add unlock here */
4510 /* BB On error, should we leave previous search buf (and count and
4511 last entry fields) intact or free the previous one? */
4513 /* Note: On -EAGAIN error only caller can retry on handle based calls
4514 since file handle passed in no longer valid */
4517 cifs_buf_release(pSMB);
4522 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4523 const __u16 searchHandle)
4526 FINDCLOSE_REQ *pSMB = NULL;
4528 cFYI(1, "In CIFSSMBFindClose");
4529 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4531 /* no sense returning error if session restarted
4532 as file handle has been closed */
4538 pSMB->FileID = searchHandle;
4539 pSMB->ByteCount = 0;
4540 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4542 cERROR(1, "Send error in FindClose = %d", rc);
4544 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4546 /* Since session is dead, search handle closed on server already */
4554 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4555 const char *search_name, __u64 *inode_number,
4556 const struct nls_table *nls_codepage, int remap)
4559 TRANSACTION2_QPI_REQ *pSMB = NULL;
4560 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4561 int name_len, bytes_returned;
4562 __u16 params, byte_count;
4564 cFYI(1, "In GetSrvInodeNum for %s", search_name);
4568 GetInodeNumberRetry:
4569 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4574 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4576 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4577 search_name, PATH_MAX, nls_codepage,
4579 name_len++; /* trailing null */
4581 } else { /* BB improve the check for buffer overruns BB */
4582 name_len = strnlen(search_name, PATH_MAX);
4583 name_len++; /* trailing null */
4584 strncpy(pSMB->FileName, search_name, name_len);
4587 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4588 pSMB->TotalDataCount = 0;
4589 pSMB->MaxParameterCount = cpu_to_le16(2);
4590 /* BB find exact max data count below from sess structure BB */
4591 pSMB->MaxDataCount = cpu_to_le16(4000);
4592 pSMB->MaxSetupCount = 0;
4596 pSMB->Reserved2 = 0;
4597 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4598 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4599 pSMB->DataCount = 0;
4600 pSMB->DataOffset = 0;
4601 pSMB->SetupCount = 1;
4602 pSMB->Reserved3 = 0;
4603 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4604 byte_count = params + 1 /* pad */ ;
4605 pSMB->TotalParameterCount = cpu_to_le16(params);
4606 pSMB->ParameterCount = pSMB->TotalParameterCount;
4607 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4608 pSMB->Reserved4 = 0;
4609 inc_rfc1001_len(pSMB, byte_count);
4610 pSMB->ByteCount = cpu_to_le16(byte_count);
4612 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4613 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4615 cFYI(1, "error %d in QueryInternalInfo", rc);
4617 /* decode response */
4618 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4619 /* BB also check enough total bytes returned */
4620 if (rc || get_bcc(&pSMBr->hdr) < 2)
4621 /* If rc should we check for EOPNOSUPP and
4622 disable the srvino flag? or in caller? */
4623 rc = -EIO; /* bad smb */
4625 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4626 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4627 struct file_internal_info *pfinfo;
4628 /* BB Do we need a cast or hash here ? */
4630 cFYI(1, "Illegal size ret in QryIntrnlInf");
4632 goto GetInodeNumOut;
4634 pfinfo = (struct file_internal_info *)
4635 (data_offset + (char *) &pSMBr->hdr.Protocol);
4636 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4640 cifs_buf_release(pSMB);
4642 goto GetInodeNumberRetry;
4646 /* parses DFS refferal V3 structure
4647 * caller is responsible for freeing target_nodes
4650 * on failure - errno
4653 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4654 unsigned int *num_of_nodes,
4655 struct dfs_info3_param **target_nodes,
4656 const struct nls_table *nls_codepage, int remap,
4657 const char *searchName)
4662 struct dfs_referral_level_3 *ref;
4664 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4668 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4670 if (*num_of_nodes < 1) {
4671 cERROR(1, "num_referrals: must be at least > 0,"
4672 "but we get num_referrals = %d", *num_of_nodes);
4674 goto parse_DFS_referrals_exit;
4677 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4678 if (ref->VersionNumber != cpu_to_le16(3)) {
4679 cERROR(1, "Referrals of V%d version are not supported,"
4680 "should be V3", le16_to_cpu(ref->VersionNumber));
4682 goto parse_DFS_referrals_exit;
4685 /* get the upper boundary of the resp buffer */
4686 data_end = (char *)(&(pSMBr->PathConsumed)) +
4687 le16_to_cpu(pSMBr->t2.DataCount);
4689 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4691 le32_to_cpu(pSMBr->DFSFlags));
4693 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4694 *num_of_nodes, GFP_KERNEL);
4695 if (*target_nodes == NULL) {
4696 cERROR(1, "Failed to allocate buffer for target_nodes");
4698 goto parse_DFS_referrals_exit;
4701 /* collect necessary data from referrals */
4702 for (i = 0; i < *num_of_nodes; i++) {
4705 struct dfs_info3_param *node = (*target_nodes)+i;
4707 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4709 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4713 goto parse_DFS_referrals_exit;
4715 cifsConvertToUTF16((__le16 *) tmp, searchName,
4716 PATH_MAX, nls_codepage, remap);
4717 node->path_consumed = cifs_utf16_bytes(tmp,
4718 le16_to_cpu(pSMBr->PathConsumed),
4722 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4724 node->server_type = le16_to_cpu(ref->ServerType);
4725 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4728 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4729 max_len = data_end - temp;
4730 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4731 is_unicode, nls_codepage);
4732 if (!node->path_name) {
4734 goto parse_DFS_referrals_exit;
4737 /* copy link target UNC */
4738 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4739 max_len = data_end - temp;
4740 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4741 is_unicode, nls_codepage);
4742 if (!node->node_name) {
4744 goto parse_DFS_referrals_exit;
4750 parse_DFS_referrals_exit:
4752 free_dfs_info_array(*target_nodes, *num_of_nodes);
4753 *target_nodes = NULL;
4760 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4761 const char *search_name, struct dfs_info3_param **target_nodes,
4762 unsigned int *num_of_nodes,
4763 const struct nls_table *nls_codepage, int remap)
4765 /* TRANS2_GET_DFS_REFERRAL */
4766 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4767 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4771 __u16 params, byte_count;
4773 *target_nodes = NULL;
4775 cFYI(1, "In GetDFSRefer the path %s", search_name);
4779 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4784 /* server pointer checked in called function,
4785 but should never be null here anyway */
4786 pSMB->hdr.Mid = get_next_mid(ses->server);
4787 pSMB->hdr.Tid = ses->ipc_tid;
4788 pSMB->hdr.Uid = ses->Suid;
4789 if (ses->capabilities & CAP_STATUS32)
4790 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4791 if (ses->capabilities & CAP_DFS)
4792 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4794 if (ses->capabilities & CAP_UNICODE) {
4795 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4797 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4798 search_name, PATH_MAX, nls_codepage,
4800 name_len++; /* trailing null */
4802 } else { /* BB improve the check for buffer overruns BB */
4803 name_len = strnlen(search_name, PATH_MAX);
4804 name_len++; /* trailing null */
4805 strncpy(pSMB->RequestFileName, search_name, name_len);
4809 if (ses->server->sec_mode &
4810 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4811 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4814 pSMB->hdr.Uid = ses->Suid;
4816 params = 2 /* level */ + name_len /*includes null */ ;
4817 pSMB->TotalDataCount = 0;
4818 pSMB->DataCount = 0;
4819 pSMB->DataOffset = 0;
4820 pSMB->MaxParameterCount = 0;
4821 /* BB find exact max SMB PDU from sess structure BB */
4822 pSMB->MaxDataCount = cpu_to_le16(4000);
4823 pSMB->MaxSetupCount = 0;
4827 pSMB->Reserved2 = 0;
4828 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4829 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4830 pSMB->SetupCount = 1;
4831 pSMB->Reserved3 = 0;
4832 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4833 byte_count = params + 3 /* pad */ ;
4834 pSMB->ParameterCount = cpu_to_le16(params);
4835 pSMB->TotalParameterCount = pSMB->ParameterCount;
4836 pSMB->MaxReferralLevel = cpu_to_le16(3);
4837 inc_rfc1001_len(pSMB, byte_count);
4838 pSMB->ByteCount = cpu_to_le16(byte_count);
4840 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4841 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4843 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4846 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4848 /* BB Also check if enough total bytes returned? */
4849 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4850 rc = -EIO; /* bad smb */
4854 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4855 get_bcc(&pSMBr->hdr),
4856 le16_to_cpu(pSMBr->t2.DataOffset));
4858 /* parse returned result into more usable form */
4859 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4860 target_nodes, nls_codepage, remap,
4864 cifs_buf_release(pSMB);
4872 /* Query File System Info such as free space to old servers such as Win 9x */
4874 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4875 struct kstatfs *FSData)
4877 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4878 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4879 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4880 FILE_SYSTEM_ALLOC_INFO *response_data;
4882 int bytes_returned = 0;
4883 __u16 params, byte_count;
4885 cFYI(1, "OldQFSInfo");
4887 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4892 params = 2; /* level */
4893 pSMB->TotalDataCount = 0;
4894 pSMB->MaxParameterCount = cpu_to_le16(2);
4895 pSMB->MaxDataCount = cpu_to_le16(1000);
4896 pSMB->MaxSetupCount = 0;
4900 pSMB->Reserved2 = 0;
4901 byte_count = params + 1 /* pad */ ;
4902 pSMB->TotalParameterCount = cpu_to_le16(params);
4903 pSMB->ParameterCount = pSMB->TotalParameterCount;
4904 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4905 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4906 pSMB->DataCount = 0;
4907 pSMB->DataOffset = 0;
4908 pSMB->SetupCount = 1;
4909 pSMB->Reserved3 = 0;
4910 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4911 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4912 inc_rfc1001_len(pSMB, byte_count);
4913 pSMB->ByteCount = cpu_to_le16(byte_count);
4915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4918 cFYI(1, "Send error in QFSInfo = %d", rc);
4919 } else { /* decode response */
4920 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4922 if (rc || get_bcc(&pSMBr->hdr) < 18)
4923 rc = -EIO; /* bad smb */
4925 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4926 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4927 get_bcc(&pSMBr->hdr), data_offset);
4929 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4930 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4932 le16_to_cpu(response_data->BytesPerSector) *
4933 le32_to_cpu(response_data->
4934 SectorsPerAllocationUnit);
4936 le32_to_cpu(response_data->TotalAllocationUnits);
4937 FSData->f_bfree = FSData->f_bavail =
4938 le32_to_cpu(response_data->FreeAllocationUnits);
4939 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4940 (unsigned long long)FSData->f_blocks,
4941 (unsigned long long)FSData->f_bfree,
4945 cifs_buf_release(pSMB);
4948 goto oldQFSInfoRetry;
4954 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4955 struct kstatfs *FSData)
4957 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4958 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4959 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4960 FILE_SYSTEM_INFO *response_data;
4962 int bytes_returned = 0;
4963 __u16 params, byte_count;
4965 cFYI(1, "In QFSInfo");
4967 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4972 params = 2; /* level */
4973 pSMB->TotalDataCount = 0;
4974 pSMB->MaxParameterCount = cpu_to_le16(2);
4975 pSMB->MaxDataCount = cpu_to_le16(1000);
4976 pSMB->MaxSetupCount = 0;
4980 pSMB->Reserved2 = 0;
4981 byte_count = params + 1 /* pad */ ;
4982 pSMB->TotalParameterCount = cpu_to_le16(params);
4983 pSMB->ParameterCount = pSMB->TotalParameterCount;
4984 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4985 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4986 pSMB->DataCount = 0;
4987 pSMB->DataOffset = 0;
4988 pSMB->SetupCount = 1;
4989 pSMB->Reserved3 = 0;
4990 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4991 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4992 inc_rfc1001_len(pSMB, byte_count);
4993 pSMB->ByteCount = cpu_to_le16(byte_count);
4995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4998 cFYI(1, "Send error in QFSInfo = %d", rc);
4999 } else { /* decode response */
5000 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5002 if (rc || get_bcc(&pSMBr->hdr) < 24)
5003 rc = -EIO; /* bad smb */
5005 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5009 *) (((char *) &pSMBr->hdr.Protocol) +
5012 le32_to_cpu(response_data->BytesPerSector) *
5013 le32_to_cpu(response_data->
5014 SectorsPerAllocationUnit);
5016 le64_to_cpu(response_data->TotalAllocationUnits);
5017 FSData->f_bfree = FSData->f_bavail =
5018 le64_to_cpu(response_data->FreeAllocationUnits);
5019 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5020 (unsigned long long)FSData->f_blocks,
5021 (unsigned long long)FSData->f_bfree,
5025 cifs_buf_release(pSMB);
5034 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5036 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5037 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5038 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5039 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5041 int bytes_returned = 0;
5042 __u16 params, byte_count;
5044 cFYI(1, "In QFSAttributeInfo");
5046 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5051 params = 2; /* level */
5052 pSMB->TotalDataCount = 0;
5053 pSMB->MaxParameterCount = cpu_to_le16(2);
5054 /* BB find exact max SMB PDU from sess structure BB */
5055 pSMB->MaxDataCount = cpu_to_le16(1000);
5056 pSMB->MaxSetupCount = 0;
5060 pSMB->Reserved2 = 0;
5061 byte_count = params + 1 /* pad */ ;
5062 pSMB->TotalParameterCount = cpu_to_le16(params);
5063 pSMB->ParameterCount = pSMB->TotalParameterCount;
5064 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5065 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5066 pSMB->DataCount = 0;
5067 pSMB->DataOffset = 0;
5068 pSMB->SetupCount = 1;
5069 pSMB->Reserved3 = 0;
5070 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5071 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5072 inc_rfc1001_len(pSMB, byte_count);
5073 pSMB->ByteCount = cpu_to_le16(byte_count);
5075 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5076 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5078 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5079 } else { /* decode response */
5080 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5082 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5083 /* BB also check if enough bytes returned */
5084 rc = -EIO; /* bad smb */
5086 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5088 (FILE_SYSTEM_ATTRIBUTE_INFO
5089 *) (((char *) &pSMBr->hdr.Protocol) +
5091 memcpy(&tcon->fsAttrInfo, response_data,
5092 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5095 cifs_buf_release(pSMB);
5098 goto QFSAttributeRetry;
5104 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5106 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5107 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5108 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5109 FILE_SYSTEM_DEVICE_INFO *response_data;
5111 int bytes_returned = 0;
5112 __u16 params, byte_count;
5114 cFYI(1, "In QFSDeviceInfo");
5116 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5121 params = 2; /* level */
5122 pSMB->TotalDataCount = 0;
5123 pSMB->MaxParameterCount = cpu_to_le16(2);
5124 /* BB find exact max SMB PDU from sess structure BB */
5125 pSMB->MaxDataCount = cpu_to_le16(1000);
5126 pSMB->MaxSetupCount = 0;
5130 pSMB->Reserved2 = 0;
5131 byte_count = params + 1 /* pad */ ;
5132 pSMB->TotalParameterCount = cpu_to_le16(params);
5133 pSMB->ParameterCount = pSMB->TotalParameterCount;
5134 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5135 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5137 pSMB->DataCount = 0;
5138 pSMB->DataOffset = 0;
5139 pSMB->SetupCount = 1;
5140 pSMB->Reserved3 = 0;
5141 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5142 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5143 inc_rfc1001_len(pSMB, byte_count);
5144 pSMB->ByteCount = cpu_to_le16(byte_count);
5146 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5147 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5149 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5150 } else { /* decode response */
5151 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5153 if (rc || get_bcc(&pSMBr->hdr) <
5154 sizeof(FILE_SYSTEM_DEVICE_INFO))
5155 rc = -EIO; /* bad smb */
5157 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5159 (FILE_SYSTEM_DEVICE_INFO *)
5160 (((char *) &pSMBr->hdr.Protocol) +
5162 memcpy(&tcon->fsDevInfo, response_data,
5163 sizeof(FILE_SYSTEM_DEVICE_INFO));
5166 cifs_buf_release(pSMB);
5169 goto QFSDeviceRetry;
5175 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5177 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5178 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5179 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5180 FILE_SYSTEM_UNIX_INFO *response_data;
5182 int bytes_returned = 0;
5183 __u16 params, byte_count;
5185 cFYI(1, "In QFSUnixInfo");
5187 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5188 (void **) &pSMB, (void **) &pSMBr);
5192 params = 2; /* level */
5193 pSMB->TotalDataCount = 0;
5194 pSMB->DataCount = 0;
5195 pSMB->DataOffset = 0;
5196 pSMB->MaxParameterCount = cpu_to_le16(2);
5197 /* BB find exact max SMB PDU from sess structure BB */
5198 pSMB->MaxDataCount = cpu_to_le16(100);
5199 pSMB->MaxSetupCount = 0;
5203 pSMB->Reserved2 = 0;
5204 byte_count = params + 1 /* pad */ ;
5205 pSMB->ParameterCount = cpu_to_le16(params);
5206 pSMB->TotalParameterCount = pSMB->ParameterCount;
5207 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5208 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5209 pSMB->SetupCount = 1;
5210 pSMB->Reserved3 = 0;
5211 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5212 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5213 inc_rfc1001_len(pSMB, byte_count);
5214 pSMB->ByteCount = cpu_to_le16(byte_count);
5216 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5217 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5219 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5220 } else { /* decode response */
5221 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5223 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5224 rc = -EIO; /* bad smb */
5226 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5228 (FILE_SYSTEM_UNIX_INFO
5229 *) (((char *) &pSMBr->hdr.Protocol) +
5231 memcpy(&tcon->fsUnixInfo, response_data,
5232 sizeof(FILE_SYSTEM_UNIX_INFO));
5235 cifs_buf_release(pSMB);
5245 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5247 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5248 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5249 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5251 int bytes_returned = 0;
5252 __u16 params, param_offset, offset, byte_count;
5254 cFYI(1, "In SETFSUnixInfo");
5256 /* BB switch to small buf init to save memory */
5257 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5258 (void **) &pSMB, (void **) &pSMBr);
5262 params = 4; /* 2 bytes zero followed by info level. */
5263 pSMB->MaxSetupCount = 0;
5267 pSMB->Reserved2 = 0;
5268 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5270 offset = param_offset + params;
5272 pSMB->MaxParameterCount = cpu_to_le16(4);
5273 /* BB find exact max SMB PDU from sess structure BB */
5274 pSMB->MaxDataCount = cpu_to_le16(100);
5275 pSMB->SetupCount = 1;
5276 pSMB->Reserved3 = 0;
5277 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5278 byte_count = 1 /* pad */ + params + 12;
5280 pSMB->DataCount = cpu_to_le16(12);
5281 pSMB->ParameterCount = cpu_to_le16(params);
5282 pSMB->TotalDataCount = pSMB->DataCount;
5283 pSMB->TotalParameterCount = pSMB->ParameterCount;
5284 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5285 pSMB->DataOffset = cpu_to_le16(offset);
5289 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5292 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5293 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5294 pSMB->ClientUnixCap = cpu_to_le64(cap);
5296 inc_rfc1001_len(pSMB, byte_count);
5297 pSMB->ByteCount = cpu_to_le16(byte_count);
5299 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5300 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5302 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5303 } else { /* decode response */
5304 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5306 rc = -EIO; /* bad smb */
5308 cifs_buf_release(pSMB);
5311 goto SETFSUnixRetry;
5319 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5320 struct kstatfs *FSData)
5322 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5323 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5324 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5325 FILE_SYSTEM_POSIX_INFO *response_data;
5327 int bytes_returned = 0;
5328 __u16 params, byte_count;
5330 cFYI(1, "In QFSPosixInfo");
5332 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5337 params = 2; /* level */
5338 pSMB->TotalDataCount = 0;
5339 pSMB->DataCount = 0;
5340 pSMB->DataOffset = 0;
5341 pSMB->MaxParameterCount = cpu_to_le16(2);
5342 /* BB find exact max SMB PDU from sess structure BB */
5343 pSMB->MaxDataCount = cpu_to_le16(100);
5344 pSMB->MaxSetupCount = 0;
5348 pSMB->Reserved2 = 0;
5349 byte_count = params + 1 /* pad */ ;
5350 pSMB->ParameterCount = cpu_to_le16(params);
5351 pSMB->TotalParameterCount = pSMB->ParameterCount;
5352 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5353 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5354 pSMB->SetupCount = 1;
5355 pSMB->Reserved3 = 0;
5356 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5357 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5358 inc_rfc1001_len(pSMB, byte_count);
5359 pSMB->ByteCount = cpu_to_le16(byte_count);
5361 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5364 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5365 } else { /* decode response */
5366 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5368 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5369 rc = -EIO; /* bad smb */
5371 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5373 (FILE_SYSTEM_POSIX_INFO
5374 *) (((char *) &pSMBr->hdr.Protocol) +
5377 le32_to_cpu(response_data->BlockSize);
5379 le64_to_cpu(response_data->TotalBlocks);
5381 le64_to_cpu(response_data->BlocksAvail);
5382 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5383 FSData->f_bavail = FSData->f_bfree;
5386 le64_to_cpu(response_data->UserBlocksAvail);
5388 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5390 le64_to_cpu(response_data->TotalFileNodes);
5391 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5393 le64_to_cpu(response_data->FreeFileNodes);
5396 cifs_buf_release(pSMB);
5406 * We can not use write of zero bytes trick to set file size due to need for
5407 * large file support. Also note that this SetPathInfo is preferred to
5408 * SetFileInfo based method in next routine which is only needed to work around
5409 * a sharing violation bugin Samba which this routine can run into.
5412 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5413 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5414 bool set_allocation)
5416 struct smb_com_transaction2_spi_req *pSMB = NULL;
5417 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5418 struct file_end_of_file_info *parm_data;
5421 int bytes_returned = 0;
5422 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
5424 __u16 params, byte_count, data_count, param_offset, offset;
5426 cFYI(1, "In SetEOF");
5428 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5433 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5435 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5436 PATH_MAX, cifs_sb->local_nls, remap);
5437 name_len++; /* trailing null */
5439 } else { /* BB improve the check for buffer overruns BB */
5440 name_len = strnlen(file_name, PATH_MAX);
5441 name_len++; /* trailing null */
5442 strncpy(pSMB->FileName, file_name, name_len);
5444 params = 6 + name_len;
5445 data_count = sizeof(struct file_end_of_file_info);
5446 pSMB->MaxParameterCount = cpu_to_le16(2);
5447 pSMB->MaxDataCount = cpu_to_le16(4100);
5448 pSMB->MaxSetupCount = 0;
5452 pSMB->Reserved2 = 0;
5453 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5454 InformationLevel) - 4;
5455 offset = param_offset + params;
5456 if (set_allocation) {
5457 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5458 pSMB->InformationLevel =
5459 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5461 pSMB->InformationLevel =
5462 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5463 } else /* Set File Size */ {
5464 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5465 pSMB->InformationLevel =
5466 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5468 pSMB->InformationLevel =
5469 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5473 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5475 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5476 pSMB->DataOffset = cpu_to_le16(offset);
5477 pSMB->SetupCount = 1;
5478 pSMB->Reserved3 = 0;
5479 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5480 byte_count = 3 /* pad */ + params + data_count;
5481 pSMB->DataCount = cpu_to_le16(data_count);
5482 pSMB->TotalDataCount = pSMB->DataCount;
5483 pSMB->ParameterCount = cpu_to_le16(params);
5484 pSMB->TotalParameterCount = pSMB->ParameterCount;
5485 pSMB->Reserved4 = 0;
5486 inc_rfc1001_len(pSMB, byte_count);
5487 parm_data->FileSize = cpu_to_le64(size);
5488 pSMB->ByteCount = cpu_to_le16(byte_count);
5489 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5490 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5492 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5494 cifs_buf_release(pSMB);
5503 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5504 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5506 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5507 struct file_end_of_file_info *parm_data;
5509 __u16 params, param_offset, offset, byte_count, count;
5511 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5513 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5518 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5519 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5522 pSMB->MaxSetupCount = 0;
5526 pSMB->Reserved2 = 0;
5527 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5528 offset = param_offset + params;
5530 count = sizeof(struct file_end_of_file_info);
5531 pSMB->MaxParameterCount = cpu_to_le16(2);
5532 /* BB find exact max SMB PDU from sess structure BB */
5533 pSMB->MaxDataCount = cpu_to_le16(1000);
5534 pSMB->SetupCount = 1;
5535 pSMB->Reserved3 = 0;
5536 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5537 byte_count = 3 /* pad */ + params + count;
5538 pSMB->DataCount = cpu_to_le16(count);
5539 pSMB->ParameterCount = cpu_to_le16(params);
5540 pSMB->TotalDataCount = pSMB->DataCount;
5541 pSMB->TotalParameterCount = pSMB->ParameterCount;
5542 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5544 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5546 pSMB->DataOffset = cpu_to_le16(offset);
5547 parm_data->FileSize = cpu_to_le64(size);
5548 pSMB->Fid = cfile->fid.netfid;
5549 if (set_allocation) {
5550 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5551 pSMB->InformationLevel =
5552 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5554 pSMB->InformationLevel =
5555 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5556 } else /* Set File Size */ {
5557 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5558 pSMB->InformationLevel =
5559 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5561 pSMB->InformationLevel =
5562 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5564 pSMB->Reserved4 = 0;
5565 inc_rfc1001_len(pSMB, byte_count);
5566 pSMB->ByteCount = cpu_to_le16(byte_count);
5567 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5569 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5572 /* Note: On -EAGAIN error only caller can retry on handle based calls
5573 since file handle passed in no longer valid */
5578 /* Some legacy servers such as NT4 require that the file times be set on
5579 an open handle, rather than by pathname - this is awkward due to
5580 potential access conflicts on the open, but it is unavoidable for these
5581 old servers since the only other choice is to go from 100 nanosecond DCE
5582 time and resort to the original setpathinfo level which takes the ancient
5583 DOS time format with 2 second granularity */
5585 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5586 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5588 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5591 __u16 params, param_offset, offset, byte_count, count;
5593 cFYI(1, "Set Times (via SetFileInfo)");
5594 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5599 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5600 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5603 pSMB->MaxSetupCount = 0;
5607 pSMB->Reserved2 = 0;
5608 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5609 offset = param_offset + params;
5611 data_offset = (char *)pSMB +
5612 offsetof(struct smb_hdr, Protocol) + offset;
5614 count = sizeof(FILE_BASIC_INFO);
5615 pSMB->MaxParameterCount = cpu_to_le16(2);
5616 /* BB find max SMB PDU from sess */
5617 pSMB->MaxDataCount = cpu_to_le16(1000);
5618 pSMB->SetupCount = 1;
5619 pSMB->Reserved3 = 0;
5620 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5621 byte_count = 3 /* pad */ + params + count;
5622 pSMB->DataCount = cpu_to_le16(count);
5623 pSMB->ParameterCount = cpu_to_le16(params);
5624 pSMB->TotalDataCount = pSMB->DataCount;
5625 pSMB->TotalParameterCount = pSMB->ParameterCount;
5626 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5627 pSMB->DataOffset = cpu_to_le16(offset);
5629 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5630 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5632 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5633 pSMB->Reserved4 = 0;
5634 inc_rfc1001_len(pSMB, byte_count);
5635 pSMB->ByteCount = cpu_to_le16(byte_count);
5636 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5637 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5639 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5641 /* Note: On -EAGAIN error only caller can retry on handle based calls
5642 since file handle passed in no longer valid */
5648 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5649 bool delete_file, __u16 fid, __u32 pid_of_opener)
5651 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5654 __u16 params, param_offset, offset, byte_count, count;
5656 cFYI(1, "Set File Disposition (via SetFileInfo)");
5657 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5662 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5663 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5666 pSMB->MaxSetupCount = 0;
5670 pSMB->Reserved2 = 0;
5671 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5672 offset = param_offset + params;
5674 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5677 pSMB->MaxParameterCount = cpu_to_le16(2);
5678 /* BB find max SMB PDU from sess */
5679 pSMB->MaxDataCount = cpu_to_le16(1000);
5680 pSMB->SetupCount = 1;
5681 pSMB->Reserved3 = 0;
5682 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5683 byte_count = 3 /* pad */ + params + count;
5684 pSMB->DataCount = cpu_to_le16(count);
5685 pSMB->ParameterCount = cpu_to_le16(params);
5686 pSMB->TotalDataCount = pSMB->DataCount;
5687 pSMB->TotalParameterCount = pSMB->ParameterCount;
5688 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5689 pSMB->DataOffset = cpu_to_le16(offset);
5691 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5692 pSMB->Reserved4 = 0;
5693 inc_rfc1001_len(pSMB, byte_count);
5694 pSMB->ByteCount = cpu_to_le16(byte_count);
5695 *data_offset = delete_file ? 1 : 0;
5696 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5698 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5704 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5705 const char *fileName, const FILE_BASIC_INFO *data,
5706 const struct nls_table *nls_codepage, int remap)
5708 TRANSACTION2_SPI_REQ *pSMB = NULL;
5709 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5712 int bytes_returned = 0;
5714 __u16 params, param_offset, offset, byte_count, count;
5716 cFYI(1, "In SetTimes");
5719 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5724 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5726 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5727 PATH_MAX, nls_codepage, remap);
5728 name_len++; /* trailing null */
5730 } else { /* BB improve the check for buffer overruns BB */
5731 name_len = strnlen(fileName, PATH_MAX);
5732 name_len++; /* trailing null */
5733 strncpy(pSMB->FileName, fileName, name_len);
5736 params = 6 + name_len;
5737 count = sizeof(FILE_BASIC_INFO);
5738 pSMB->MaxParameterCount = cpu_to_le16(2);
5739 /* BB find max SMB PDU from sess structure BB */
5740 pSMB->MaxDataCount = cpu_to_le16(1000);
5741 pSMB->MaxSetupCount = 0;
5745 pSMB->Reserved2 = 0;
5746 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5747 InformationLevel) - 4;
5748 offset = param_offset + params;
5749 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5750 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5751 pSMB->DataOffset = cpu_to_le16(offset);
5752 pSMB->SetupCount = 1;
5753 pSMB->Reserved3 = 0;
5754 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5755 byte_count = 3 /* pad */ + params + count;
5757 pSMB->DataCount = cpu_to_le16(count);
5758 pSMB->ParameterCount = cpu_to_le16(params);
5759 pSMB->TotalDataCount = pSMB->DataCount;
5760 pSMB->TotalParameterCount = pSMB->ParameterCount;
5761 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5762 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5764 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5765 pSMB->Reserved4 = 0;
5766 inc_rfc1001_len(pSMB, byte_count);
5767 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5768 pSMB->ByteCount = cpu_to_le16(byte_count);
5769 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5770 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5772 cFYI(1, "SetPathInfo (times) returned %d", rc);
5774 cifs_buf_release(pSMB);
5782 /* Can not be used to set time stamps yet (due to old DOS time format) */
5783 /* Can be used to set attributes */
5784 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5785 handling it anyway and NT4 was what we thought it would be needed for
5786 Do not delete it until we prove whether needed for Win9x though */
5788 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5789 __u16 dos_attrs, const struct nls_table *nls_codepage)
5791 SETATTR_REQ *pSMB = NULL;
5792 SETATTR_RSP *pSMBr = NULL;
5797 cFYI(1, "In SetAttrLegacy");
5800 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5807 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5808 PATH_MAX, nls_codepage);
5809 name_len++; /* trailing null */
5811 } else { /* BB improve the check for buffer overruns BB */
5812 name_len = strnlen(fileName, PATH_MAX);
5813 name_len++; /* trailing null */
5814 strncpy(pSMB->fileName, fileName, name_len);
5816 pSMB->attr = cpu_to_le16(dos_attrs);
5817 pSMB->BufferFormat = 0x04;
5818 inc_rfc1001_len(pSMB, name_len + 1);
5819 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5820 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5821 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5823 cFYI(1, "Error in LegacySetAttr = %d", rc);
5825 cifs_buf_release(pSMB);
5828 goto SetAttrLgcyRetry;
5832 #endif /* temporarily unneeded SetAttr legacy function */
5835 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5836 const struct cifs_unix_set_info_args *args)
5838 u64 mode = args->mode;
5841 * Samba server ignores set of file size to zero due to bugs in some
5842 * older clients, but we should be precise - we use SetFileSize to
5843 * set file size and do not want to truncate file size to zero
5844 * accidentally as happened on one Samba server beta by putting
5845 * zero instead of -1 here
5847 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5848 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5849 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5850 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5851 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5852 data_offset->Uid = cpu_to_le64(args->uid);
5853 data_offset->Gid = cpu_to_le64(args->gid);
5854 /* better to leave device as zero when it is */
5855 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5856 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5857 data_offset->Permissions = cpu_to_le64(mode);
5860 data_offset->Type = cpu_to_le32(UNIX_FILE);
5861 else if (S_ISDIR(mode))
5862 data_offset->Type = cpu_to_le32(UNIX_DIR);
5863 else if (S_ISLNK(mode))
5864 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5865 else if (S_ISCHR(mode))
5866 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5867 else if (S_ISBLK(mode))
5868 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5869 else if (S_ISFIFO(mode))
5870 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5871 else if (S_ISSOCK(mode))
5872 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5876 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5877 const struct cifs_unix_set_info_args *args,
5878 u16 fid, u32 pid_of_opener)
5880 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5883 u16 params, param_offset, offset, byte_count, count;
5885 cFYI(1, "Set Unix Info (via SetFileInfo)");
5886 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5891 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5892 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5895 pSMB->MaxSetupCount = 0;
5899 pSMB->Reserved2 = 0;
5900 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5901 offset = param_offset + params;
5903 data_offset = (char *)pSMB +
5904 offsetof(struct smb_hdr, Protocol) + offset;
5906 count = sizeof(FILE_UNIX_BASIC_INFO);
5908 pSMB->MaxParameterCount = cpu_to_le16(2);
5909 /* BB find max SMB PDU from sess */
5910 pSMB->MaxDataCount = cpu_to_le16(1000);
5911 pSMB->SetupCount = 1;
5912 pSMB->Reserved3 = 0;
5913 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5914 byte_count = 3 /* pad */ + params + count;
5915 pSMB->DataCount = cpu_to_le16(count);
5916 pSMB->ParameterCount = cpu_to_le16(params);
5917 pSMB->TotalDataCount = pSMB->DataCount;
5918 pSMB->TotalParameterCount = pSMB->ParameterCount;
5919 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5920 pSMB->DataOffset = cpu_to_le16(offset);
5922 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5923 pSMB->Reserved4 = 0;
5924 inc_rfc1001_len(pSMB, byte_count);
5925 pSMB->ByteCount = cpu_to_le16(byte_count);
5927 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5929 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5931 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5933 /* Note: On -EAGAIN error only caller can retry on handle based calls
5934 since file handle passed in no longer valid */
5940 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5941 const char *file_name,
5942 const struct cifs_unix_set_info_args *args,
5943 const struct nls_table *nls_codepage, int remap)
5945 TRANSACTION2_SPI_REQ *pSMB = NULL;
5946 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5949 int bytes_returned = 0;
5950 FILE_UNIX_BASIC_INFO *data_offset;
5951 __u16 params, param_offset, offset, count, byte_count;
5953 cFYI(1, "In SetUID/GID/Mode");
5955 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5962 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5963 PATH_MAX, nls_codepage, remap);
5964 name_len++; /* trailing null */
5966 } else { /* BB improve the check for buffer overruns BB */
5967 name_len = strnlen(file_name, PATH_MAX);
5968 name_len++; /* trailing null */
5969 strncpy(pSMB->FileName, file_name, name_len);
5972 params = 6 + name_len;
5973 count = sizeof(FILE_UNIX_BASIC_INFO);
5974 pSMB->MaxParameterCount = cpu_to_le16(2);
5975 /* BB find max SMB PDU from sess structure BB */
5976 pSMB->MaxDataCount = cpu_to_le16(1000);
5977 pSMB->MaxSetupCount = 0;
5981 pSMB->Reserved2 = 0;
5982 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5983 InformationLevel) - 4;
5984 offset = param_offset + params;
5986 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5988 memset(data_offset, 0, count);
5989 pSMB->DataOffset = cpu_to_le16(offset);
5990 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5991 pSMB->SetupCount = 1;
5992 pSMB->Reserved3 = 0;
5993 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5994 byte_count = 3 /* pad */ + params + count;
5995 pSMB->ParameterCount = cpu_to_le16(params);
5996 pSMB->DataCount = cpu_to_le16(count);
5997 pSMB->TotalParameterCount = pSMB->ParameterCount;
5998 pSMB->TotalDataCount = pSMB->DataCount;
5999 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6000 pSMB->Reserved4 = 0;
6001 inc_rfc1001_len(pSMB, byte_count);
6003 cifs_fill_unix_set_info(data_offset, args);
6005 pSMB->ByteCount = cpu_to_le16(byte_count);
6006 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6007 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6009 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6011 cifs_buf_release(pSMB);
6017 #ifdef CONFIG_CIFS_XATTR
6019 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6020 * function used by listxattr and getxattr type calls. When ea_name is set,
6021 * it looks for that attribute name and stuffs that value into the EAData
6022 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6023 * buffer. In both cases, the return value is either the length of the
6024 * resulting data or a negative error code. If EAData is a NULL pointer then
6025 * the data isn't copied to it, but the length is returned.
6028 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6029 const unsigned char *searchName, const unsigned char *ea_name,
6030 char *EAData, size_t buf_size,
6031 const struct nls_table *nls_codepage, int remap)
6033 /* BB assumes one setup word */
6034 TRANSACTION2_QPI_REQ *pSMB = NULL;
6035 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6039 struct fealist *ea_response_data;
6040 struct fea *temp_fea;
6043 __u16 params, byte_count, data_offset;
6044 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6046 cFYI(1, "In Query All EAs path %s", searchName);
6048 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6053 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6055 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6056 PATH_MAX, nls_codepage, remap);
6057 list_len++; /* trailing null */
6059 } else { /* BB improve the check for buffer overruns BB */
6060 list_len = strnlen(searchName, PATH_MAX);
6061 list_len++; /* trailing null */
6062 strncpy(pSMB->FileName, searchName, list_len);
6065 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6066 pSMB->TotalDataCount = 0;
6067 pSMB->MaxParameterCount = cpu_to_le16(2);
6068 /* BB find exact max SMB PDU from sess structure BB */
6069 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6070 pSMB->MaxSetupCount = 0;
6074 pSMB->Reserved2 = 0;
6075 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6076 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6077 pSMB->DataCount = 0;
6078 pSMB->DataOffset = 0;
6079 pSMB->SetupCount = 1;
6080 pSMB->Reserved3 = 0;
6081 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6082 byte_count = params + 1 /* pad */ ;
6083 pSMB->TotalParameterCount = cpu_to_le16(params);
6084 pSMB->ParameterCount = pSMB->TotalParameterCount;
6085 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6086 pSMB->Reserved4 = 0;
6087 inc_rfc1001_len(pSMB, byte_count);
6088 pSMB->ByteCount = cpu_to_le16(byte_count);
6090 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6093 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6098 /* BB also check enough total bytes returned */
6099 /* BB we need to improve the validity checking
6100 of these trans2 responses */
6102 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6103 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6104 rc = -EIO; /* bad smb */
6108 /* check that length of list is not more than bcc */
6109 /* check that each entry does not go beyond length
6111 /* check that each element of each entry does not
6112 go beyond end of list */
6113 /* validate_trans2_offsets() */
6114 /* BB check if start of smb + data_offset > &bcc+ bcc */
6116 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6117 ea_response_data = (struct fealist *)
6118 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6120 list_len = le32_to_cpu(ea_response_data->list_len);
6121 cFYI(1, "ea length %d", list_len);
6122 if (list_len <= 8) {
6123 cFYI(1, "empty EA list returned from server");
6127 /* make sure list_len doesn't go past end of SMB */
6128 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6129 if ((char *)ea_response_data + list_len > end_of_smb) {
6130 cFYI(1, "EA list appears to go beyond SMB");
6135 /* account for ea list len */
6137 temp_fea = ea_response_data->list;
6138 temp_ptr = (char *)temp_fea;
6139 while (list_len > 0) {
6140 unsigned int name_len;
6145 /* make sure we can read name_len and value_len */
6147 cFYI(1, "EA entry goes beyond length of list");
6152 name_len = temp_fea->name_len;
6153 value_len = le16_to_cpu(temp_fea->value_len);
6154 list_len -= name_len + 1 + value_len;
6156 cFYI(1, "EA entry goes beyond length of list");
6162 if (ea_name_len == name_len &&
6163 memcmp(ea_name, temp_ptr, name_len) == 0) {
6164 temp_ptr += name_len + 1;
6168 if ((size_t)value_len > buf_size) {
6172 memcpy(EAData, temp_ptr, value_len);
6176 /* account for prefix user. and trailing null */
6177 rc += (5 + 1 + name_len);
6178 if (rc < (int) buf_size) {
6179 memcpy(EAData, "user.", 5);
6181 memcpy(EAData, temp_ptr, name_len);
6183 /* null terminate name */
6186 } else if (buf_size == 0) {
6187 /* skip copy - calc size only */
6189 /* stop before overrun buffer */
6194 temp_ptr += name_len + 1 + value_len;
6195 temp_fea = (struct fea *)temp_ptr;
6198 /* didn't find the named attribute */
6203 cifs_buf_release(pSMB);
6211 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6212 const char *fileName, const char *ea_name, const void *ea_value,
6213 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6216 struct smb_com_transaction2_spi_req *pSMB = NULL;
6217 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6218 struct fealist *parm_data;
6221 int bytes_returned = 0;
6222 __u16 params, param_offset, byte_count, offset, count;
6224 cFYI(1, "In SetEA");
6226 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6231 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6233 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6234 PATH_MAX, nls_codepage, remap);
6235 name_len++; /* trailing null */
6237 } else { /* BB improve the check for buffer overruns BB */
6238 name_len = strnlen(fileName, PATH_MAX);
6239 name_len++; /* trailing null */
6240 strncpy(pSMB->FileName, fileName, name_len);
6243 params = 6 + name_len;
6245 /* done calculating parms using name_len of file name,
6246 now use name_len to calculate length of ea name
6247 we are going to create in the inode xattrs */
6248 if (ea_name == NULL)
6251 name_len = strnlen(ea_name, 255);
6253 count = sizeof(*parm_data) + ea_value_len + name_len;
6254 pSMB->MaxParameterCount = cpu_to_le16(2);
6255 /* BB find max SMB PDU from sess */
6256 pSMB->MaxDataCount = cpu_to_le16(1000);
6257 pSMB->MaxSetupCount = 0;
6261 pSMB->Reserved2 = 0;
6262 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6263 InformationLevel) - 4;
6264 offset = param_offset + params;
6265 pSMB->InformationLevel =
6266 cpu_to_le16(SMB_SET_FILE_EA);
6269 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6271 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6272 pSMB->DataOffset = cpu_to_le16(offset);
6273 pSMB->SetupCount = 1;
6274 pSMB->Reserved3 = 0;
6275 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6276 byte_count = 3 /* pad */ + params + count;
6277 pSMB->DataCount = cpu_to_le16(count);
6278 parm_data->list_len = cpu_to_le32(count);
6279 parm_data->list[0].EA_flags = 0;
6280 /* we checked above that name len is less than 255 */
6281 parm_data->list[0].name_len = (__u8)name_len;
6282 /* EA names are always ASCII */
6284 strncpy(parm_data->list[0].name, ea_name, name_len);
6285 parm_data->list[0].name[name_len] = 0;
6286 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6287 /* caller ensures that ea_value_len is less than 64K but
6288 we need to ensure that it fits within the smb */
6290 /*BB add length check to see if it would fit in
6291 negotiated SMB buffer size BB */
6292 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6294 memcpy(parm_data->list[0].name+name_len+1,
6295 ea_value, ea_value_len);
6297 pSMB->TotalDataCount = pSMB->DataCount;
6298 pSMB->ParameterCount = cpu_to_le16(params);
6299 pSMB->TotalParameterCount = pSMB->ParameterCount;
6300 pSMB->Reserved4 = 0;
6301 inc_rfc1001_len(pSMB, byte_count);
6302 pSMB->ByteCount = cpu_to_le16(byte_count);
6303 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6304 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6306 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6308 cifs_buf_release(pSMB);
6317 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6319 * Years ago the kernel added a "dnotify" function for Samba server,
6320 * to allow network clients (such as Windows) to display updated
6321 * lists of files in directory listings automatically when
6322 * files are added by one user when another user has the
6323 * same directory open on their desktop. The Linux cifs kernel
6324 * client hooked into the kernel side of this interface for
6325 * the same reason, but ironically when the VFS moved from
6326 * "dnotify" to "inotify" it became harder to plug in Linux
6327 * network file system clients (the most obvious use case
6328 * for notify interfaces is when multiple users can update
6329 * the contents of the same directory - exactly what network
6330 * file systems can do) although the server (Samba) could
6331 * still use it. For the short term we leave the worker
6332 * function ifdeffed out (below) until inotify is fixed
6333 * in the VFS to make it easier to plug in network file
6334 * system clients. If inotify turns out to be permanently
6335 * incompatible for network fs clients, we could instead simply
6336 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6338 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6339 const int notify_subdirs, const __u16 netfid,
6340 __u32 filter, struct file *pfile, int multishot,
6341 const struct nls_table *nls_codepage)
6344 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6345 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6346 struct dir_notify_req *dnotify_req;
6349 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6350 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6355 pSMB->TotalParameterCount = 0 ;
6356 pSMB->TotalDataCount = 0;
6357 pSMB->MaxParameterCount = cpu_to_le32(2);
6358 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6359 pSMB->MaxSetupCount = 4;
6361 pSMB->ParameterOffset = 0;
6362 pSMB->DataCount = 0;
6363 pSMB->DataOffset = 0;
6364 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6365 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6366 pSMB->ParameterCount = pSMB->TotalParameterCount;
6368 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6369 pSMB->Reserved2 = 0;
6370 pSMB->CompletionFilter = cpu_to_le32(filter);
6371 pSMB->Fid = netfid; /* file handle always le */
6372 pSMB->ByteCount = 0;
6374 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6375 (struct smb_hdr *)pSMBr, &bytes_returned,
6378 cFYI(1, "Error in Notify = %d", rc);
6380 /* Add file to outstanding requests */
6381 /* BB change to kmem cache alloc */
6382 dnotify_req = kmalloc(
6383 sizeof(struct dir_notify_req),
6386 dnotify_req->Pid = pSMB->hdr.Pid;
6387 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6388 dnotify_req->Mid = pSMB->hdr.Mid;
6389 dnotify_req->Tid = pSMB->hdr.Tid;
6390 dnotify_req->Uid = pSMB->hdr.Uid;
6391 dnotify_req->netfid = netfid;
6392 dnotify_req->pfile = pfile;
6393 dnotify_req->filter = filter;
6394 dnotify_req->multishot = multishot;
6395 spin_lock(&GlobalMid_Lock);
6396 list_add_tail(&dnotify_req->lhead,
6397 &GlobalDnotifyReqList);
6398 spin_unlock(&GlobalMid_Lock);
6402 cifs_buf_release(pSMB);
6405 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */