4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
91 cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage)
97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL);
100 goto cifs_strncpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
103 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL);
106 goto cifs_strncpy_to_host_ErrExit;
107 strncpy(*dst, src, plen);
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
113 cifs_strncpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
119 /* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
123 struct cifsFileInfo *open_file = NULL;
124 struct list_head *tmp;
125 struct list_head *tmp1;
127 /* list all files open on tree connection and mark them invalid */
128 write_lock(&GlobalSMBSeslock);
129 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
131 open_file->invalidHandle = true;
133 write_unlock(&GlobalSMBSeslock);
134 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
138 /* Allocate and return pointer to an SMB request buffer, and set basic
139 SMB information in the SMB header. If the return code is zero, this
140 function must have filled in request_buf pointer */
142 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
147 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
148 check for tcp and smb session status done differently
149 for those three - in the calling routine */
151 if (tcon->tidStatus == CifsExiting) {
152 /* only tree disconnect, open, and write,
153 (and ulogoff which does not have tcon)
154 are allowed as we start force umount */
155 if ((smb_command != SMB_COM_WRITE_ANDX) &&
156 (smb_command != SMB_COM_OPEN_ANDX) &&
157 (smb_command != SMB_COM_TREE_DISCONNECT)) {
158 cFYI(1, ("can not send cmd %d while umounting",
163 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
164 (tcon->ses->server)) {
165 struct nls_table *nls_codepage;
166 /* Give Demultiplex thread up to 10 seconds to
167 reconnect, should be greater than cifs socket
168 timeout which is 7 seconds */
169 while (tcon->ses->server->tcpStatus ==
171 wait_event_interruptible_timeout(tcon->ses->server->response_q,
172 (tcon->ses->server->tcpStatus ==
174 if (tcon->ses->server->tcpStatus ==
176 /* on "soft" mounts we wait once */
178 (tcon->ses->status == CifsExiting)) {
179 cFYI(1, ("gave up waiting on "
180 "reconnect in smb_init"));
182 } /* else "hard" mount - keep retrying
183 until process is killed or server
184 comes back on-line */
185 } else /* TCP session is reestablished now */
189 nls_codepage = load_nls_default();
190 /* need to prevent multiple threads trying to
191 simultaneously reconnect the same SMB session */
192 down(&tcon->ses->sesSem);
193 if (tcon->ses->need_reconnect)
194 rc = cifs_setup_session(0, tcon->ses,
196 if (!rc && (tcon->need_reconnect)) {
197 mark_open_files_invalid(tcon);
198 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
200 up(&tcon->ses->sesSem);
201 /* BB FIXME add code to check if wsize needs
202 update due to negotiated smb buffer size
205 atomic_inc(&tconInfoReconnectCount);
206 /* tell server Unix caps we support */
207 if (tcon->ses->capabilities & CAP_UNIX)
208 reset_cifs_unix_caps(
211 NULL /* we do not know sb */,
212 NULL /* no vol info */);
215 cFYI(1, ("reconnect tcon rc = %d", rc));
216 /* Removed call to reopen open files here.
217 It is safer (and faster) to reopen files
218 one at a time as needed in read and write */
220 /* Check if handle based operation so we
221 know whether we can continue or not without
222 returning to caller to reset file handle */
223 switch (smb_command) {
224 case SMB_COM_READ_ANDX:
225 case SMB_COM_WRITE_ANDX:
227 case SMB_COM_FIND_CLOSE2:
228 case SMB_COM_LOCKING_ANDX: {
229 unload_nls(nls_codepage);
234 up(&tcon->ses->sesSem);
236 unload_nls(nls_codepage);
245 *request_buf = cifs_small_buf_get();
246 if (*request_buf == NULL) {
247 /* BB should we add a retry in here if not a writepage? */
251 header_assemble((struct smb_hdr *) *request_buf, smb_command,
255 cifs_stats_inc(&tcon->num_smbs_sent);
261 small_smb_init_no_tc(const int smb_command, const int wct,
262 struct cifsSesInfo *ses, void **request_buf)
265 struct smb_hdr *buffer;
267 rc = small_smb_init(smb_command, wct, NULL, request_buf);
271 buffer = (struct smb_hdr *)*request_buf;
272 buffer->Mid = GetNextMid(ses->server);
273 if (ses->capabilities & CAP_UNICODE)
274 buffer->Flags2 |= SMBFLG2_UNICODE;
275 if (ses->capabilities & CAP_STATUS32)
276 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
278 /* uid, tid can stay at zero as set in header assemble */
280 /* BB add support for turning on the signing when
281 this function is used after 1st of session setup requests */
286 /* If the return code is zero, this function must fill in request_buf pointer */
288 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
289 void **request_buf /* returned */ ,
290 void **response_buf /* returned */ )
294 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
295 check for tcp and smb session status done differently
296 for those three - in the calling routine */
298 if (tcon->tidStatus == CifsExiting) {
299 /* only tree disconnect, open, and write,
300 (and ulogoff which does not have tcon)
301 are allowed as we start force umount */
302 if ((smb_command != SMB_COM_WRITE_ANDX) &&
303 (smb_command != SMB_COM_OPEN_ANDX) &&
304 (smb_command != SMB_COM_TREE_DISCONNECT)) {
305 cFYI(1, ("can not send cmd %d while umounting",
311 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
312 (tcon->ses->server)) {
313 struct nls_table *nls_codepage;
314 /* Give Demultiplex thread up to 10 seconds to
315 reconnect, should be greater than cifs socket
316 timeout which is 7 seconds */
317 while (tcon->ses->server->tcpStatus ==
319 wait_event_interruptible_timeout(tcon->ses->server->response_q,
320 (tcon->ses->server->tcpStatus ==
322 if (tcon->ses->server->tcpStatus ==
324 /* on "soft" mounts we wait once */
326 (tcon->ses->status == CifsExiting)) {
327 cFYI(1, ("gave up waiting on "
328 "reconnect in smb_init"));
330 } /* else "hard" mount - keep retrying
331 until process is killed or server
333 } else /* TCP session is reestablished now */
336 nls_codepage = load_nls_default();
337 /* need to prevent multiple threads trying to
338 simultaneously reconnect the same SMB session */
339 down(&tcon->ses->sesSem);
340 if (tcon->ses->need_reconnect)
341 rc = cifs_setup_session(0, tcon->ses,
343 if (!rc && (tcon->need_reconnect)) {
344 mark_open_files_invalid(tcon);
345 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
347 up(&tcon->ses->sesSem);
348 /* BB FIXME add code to check if wsize needs
349 update due to negotiated smb buffer size
352 atomic_inc(&tconInfoReconnectCount);
353 /* tell server Unix caps we support */
354 if (tcon->ses->capabilities & CAP_UNIX)
355 reset_cifs_unix_caps(
358 NULL /* do not know sb */,
359 NULL /* no vol info */);
362 cFYI(1, ("reconnect tcon rc = %d", rc));
363 /* Removed call to reopen open files here.
364 It is safer (and faster) to reopen files
365 one at a time as needed in read and write */
367 /* Check if handle based operation so we
368 know whether we can continue or not without
369 returning to caller to reset file handle */
370 switch (smb_command) {
371 case SMB_COM_READ_ANDX:
372 case SMB_COM_WRITE_ANDX:
374 case SMB_COM_FIND_CLOSE2:
375 case SMB_COM_LOCKING_ANDX: {
376 unload_nls(nls_codepage);
381 up(&tcon->ses->sesSem);
383 unload_nls(nls_codepage);
392 *request_buf = cifs_buf_get();
393 if (*request_buf == NULL) {
394 /* BB should we add a retry in here if not a writepage? */
397 /* Although the original thought was we needed the response buf for */
398 /* potential retries of smb operations it turns out we can determine */
399 /* from the mid flags when the request buffer can be resent without */
400 /* having to use a second distinct buffer for the response */
402 *response_buf = *request_buf;
404 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
408 cifs_stats_inc(&tcon->num_smbs_sent);
413 static int validate_t2(struct smb_t2_rsp *pSMB)
419 /* check for plausible wct, bcc and t2 data and parm sizes */
420 /* check for parm and data offset going beyond end of smb */
421 if (pSMB->hdr.WordCount >= 10) {
422 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
423 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
424 /* check that bcc is at least as big as parms + data */
425 /* check that bcc is less than negotiated smb buffer */
426 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
427 if (total_size < 512) {
429 le16_to_cpu(pSMB->t2_rsp.DataCount);
430 /* BCC le converted in SendReceive */
431 pBCC = (pSMB->hdr.WordCount * 2) +
432 sizeof(struct smb_hdr) +
434 if ((total_size <= (*(u16 *)pBCC)) &&
436 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
442 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
443 sizeof(struct smb_t2_rsp) + 16);
447 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
450 NEGOTIATE_RSP *pSMBr;
454 struct TCP_Server_Info *server;
456 unsigned int secFlags;
460 server = ses->server;
465 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
466 (void **) &pSMB, (void **) &pSMBr);
470 /* if any of auth flags (ie not sign or seal) are overriden use them */
471 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
472 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
473 else /* if override flags set only sign/seal OR them with global auth */
474 secFlags = extended_security | ses->overrideSecFlg;
476 cFYI(1, ("secFlags 0x%x", secFlags));
478 pSMB->hdr.Mid = GetNextMid(server);
479 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
481 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
482 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
483 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
484 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
489 for (i = 0; i < CIFS_NUM_PROT; i++) {
490 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
491 count += strlen(protocols[i].name) + 1;
492 /* null at end of source and target buffers anyway */
494 pSMB->hdr.smb_buf_length += count;
495 pSMB->ByteCount = cpu_to_le16(count);
497 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
502 dialect = le16_to_cpu(pSMBr->DialectIndex);
503 cFYI(1, ("Dialect: %d", dialect));
504 /* Check wct = 1 error case */
505 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
506 /* core returns wct = 1, but we do not ask for core - otherwise
507 small wct just comes when dialect index is -1 indicating we
508 could not negotiate a common dialect */
511 #ifdef CONFIG_CIFS_WEAK_PW_HASH
512 } else if ((pSMBr->hdr.WordCount == 13)
513 && ((dialect == LANMAN_PROT)
514 || (dialect == LANMAN2_PROT))) {
516 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
518 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
519 (secFlags & CIFSSEC_MAY_PLNTXT))
520 server->secType = LANMAN;
522 cERROR(1, ("mount failed weak security disabled"
523 " in /proc/fs/cifs/SecurityFlags"));
527 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
531 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
532 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
533 /* even though we do not use raw we might as well set this
534 accurately, in case we ever find a need for it */
535 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
536 server->max_rw = 0xFF00;
537 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
539 server->max_rw = 0;/* do not need to use raw anyway */
540 server->capabilities = CAP_MPX_MODE;
542 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
544 /* OS/2 often does not set timezone therefore
545 * we must use server time to calc time zone.
546 * Could deviate slightly from the right zone.
547 * Smallest defined timezone difference is 15 minutes
548 * (i.e. Nepal). Rounding up/down is done to match
551 int val, seconds, remain, result;
552 struct timespec ts, utc;
554 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
555 le16_to_cpu(rsp->SrvTime.Time));
556 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
557 (int)ts.tv_sec, (int)utc.tv_sec,
558 (int)(utc.tv_sec - ts.tv_sec)));
559 val = (int)(utc.tv_sec - ts.tv_sec);
561 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
562 remain = seconds % MIN_TZ_ADJ;
563 if (remain >= (MIN_TZ_ADJ / 2))
564 result += MIN_TZ_ADJ;
567 server->timeAdj = result;
569 server->timeAdj = (int)tmp;
570 server->timeAdj *= 60; /* also in seconds */
572 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
575 /* BB get server time for time conversions and add
576 code to use it and timezone since this is not UTC */
578 if (rsp->EncryptionKeyLength ==
579 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
580 memcpy(server->cryptKey, rsp->EncryptionKey,
581 CIFS_CRYPTO_KEY_SIZE);
582 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
583 rc = -EIO; /* need cryptkey unless plain text */
587 cFYI(1, ("LANMAN negotiated"));
588 /* we will not end up setting signing flags - as no signing
589 was in LANMAN and server did not return the flags on */
591 #else /* weak security disabled */
592 } else if (pSMBr->hdr.WordCount == 13) {
593 cERROR(1, ("mount failed, cifs module not built "
594 "with CIFS_WEAK_PW_HASH support"));
596 #endif /* WEAK_PW_HASH */
598 } else if (pSMBr->hdr.WordCount != 17) {
603 /* else wct == 17 NTLM */
604 server->secMode = pSMBr->SecurityMode;
605 if ((server->secMode & SECMODE_USER) == 0)
606 cFYI(1, ("share mode security"));
608 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
609 #ifdef CONFIG_CIFS_WEAK_PW_HASH
610 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
611 #endif /* CIFS_WEAK_PW_HASH */
612 cERROR(1, ("Server requests plain text password"
613 " but client support disabled"));
615 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
616 server->secType = NTLMv2;
617 else if (secFlags & CIFSSEC_MAY_NTLM)
618 server->secType = NTLM;
619 else if (secFlags & CIFSSEC_MAY_NTLMV2)
620 server->secType = NTLMv2;
621 else if (secFlags & CIFSSEC_MAY_KRB5)
622 server->secType = Kerberos;
623 else if (secFlags & CIFSSEC_MAY_LANMAN)
624 server->secType = LANMAN;
625 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
626 else if (secFlags & CIFSSEC_MAY_PLNTXT)
631 cERROR(1, ("Invalid security type"));
634 /* else ... any others ...? */
636 /* one byte, so no need to convert this or EncryptionKeyLen from
638 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
639 /* probably no need to store and check maxvcs */
640 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
641 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
642 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
643 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
644 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
645 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
646 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
647 server->timeAdj *= 60;
648 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
649 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
650 CIFS_CRYPTO_KEY_SIZE);
651 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
652 && (pSMBr->EncryptionKeyLength == 0)) {
653 /* decode security blob */
654 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
655 rc = -EIO; /* no crypt key only if plain text pwd */
659 /* BB might be helpful to save off the domain of server here */
661 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
662 (server->capabilities & CAP_EXTENDED_SECURITY)) {
663 count = pSMBr->ByteCount;
668 read_lock(&cifs_tcp_ses_lock);
669 if (server->srv_count > 1) {
670 read_unlock(&cifs_tcp_ses_lock);
671 if (memcmp(server->server_GUID,
672 pSMBr->u.extended_response.
674 cFYI(1, ("server UID changed"));
675 memcpy(server->server_GUID,
676 pSMBr->u.extended_response.GUID,
680 read_unlock(&cifs_tcp_ses_lock);
681 memcpy(server->server_GUID,
682 pSMBr->u.extended_response.GUID, 16);
686 server->secType = RawNTLMSSP;
688 rc = decode_negTokenInit(pSMBr->u.extended_response.
698 server->capabilities &= ~CAP_EXTENDED_SECURITY;
700 #ifdef CONFIG_CIFS_WEAK_PW_HASH
703 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
704 /* MUST_SIGN already includes the MAY_SIGN FLAG
705 so if this is zero it means that signing is disabled */
706 cFYI(1, ("Signing disabled"));
707 if (server->secMode & SECMODE_SIGN_REQUIRED) {
708 cERROR(1, ("Server requires "
709 "packet signing to be enabled in "
710 "/proc/fs/cifs/SecurityFlags."));
714 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
715 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
716 /* signing required */
717 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
718 if ((server->secMode &
719 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
721 ("signing required but server lacks support"));
724 server->secMode |= SECMODE_SIGN_REQUIRED;
726 /* signing optional ie CIFSSEC_MAY_SIGN */
727 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
729 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
733 cifs_buf_release(pSMB);
735 cFYI(1, ("negprot rc %d", rc));
740 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
742 struct smb_hdr *smb_buffer;
745 cFYI(1, ("In tree disconnect"));
747 /* BB: do we need to check this? These should never be NULL. */
748 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
752 * No need to return error on this operation if tid invalidated and
753 * closed on server already e.g. due to tcp session crashing. Also,
754 * the tcon is no longer on the list, so no need to take lock before
757 if (tcon->need_reconnect)
760 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
761 (void **)&smb_buffer);
765 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
767 cFYI(1, ("Tree disconnect failed %d", rc));
769 /* No need to return error on this operation if tid invalidated and
770 closed on server already e.g. due to tcp session crashing */
778 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
780 LOGOFF_ANDX_REQ *pSMB;
783 cFYI(1, ("In SMBLogoff for session disconnect"));
786 * BB: do we need to check validity of ses and server? They should
787 * always be valid since we have an active reference. If not, that
788 * should probably be a BUG()
790 if (!ses || !ses->server)
794 if (ses->need_reconnect)
795 goto session_already_dead; /* no need to send SMBlogoff if uid
796 already closed due to reconnect */
797 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
803 pSMB->hdr.Mid = GetNextMid(ses->server);
805 if (ses->server->secMode &
806 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
807 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
809 pSMB->hdr.Uid = ses->Suid;
811 pSMB->AndXCommand = 0xFF;
812 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
813 session_already_dead:
816 /* if session dead then we do not need to do ulogoff,
817 since server closed smb session, no sense reporting
825 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
826 __u16 type, const struct nls_table *nls_codepage, int remap)
828 TRANSACTION2_SPI_REQ *pSMB = NULL;
829 TRANSACTION2_SPI_RSP *pSMBr = NULL;
830 struct unlink_psx_rq *pRqD;
833 int bytes_returned = 0;
834 __u16 params, param_offset, offset, byte_count;
836 cFYI(1, ("In POSIX delete"));
838 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
843 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
845 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
846 PATH_MAX, nls_codepage, remap);
847 name_len++; /* trailing null */
849 } else { /* BB add path length overrun check */
850 name_len = strnlen(fileName, PATH_MAX);
851 name_len++; /* trailing null */
852 strncpy(pSMB->FileName, fileName, name_len);
855 params = 6 + name_len;
856 pSMB->MaxParameterCount = cpu_to_le16(2);
857 pSMB->MaxDataCount = 0; /* BB double check this with jra */
858 pSMB->MaxSetupCount = 0;
863 param_offset = offsetof(struct smb_com_transaction2_spi_req,
864 InformationLevel) - 4;
865 offset = param_offset + params;
867 /* Setup pointer to Request Data (inode type) */
868 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
869 pRqD->type = cpu_to_le16(type);
870 pSMB->ParameterOffset = cpu_to_le16(param_offset);
871 pSMB->DataOffset = cpu_to_le16(offset);
872 pSMB->SetupCount = 1;
874 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
875 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
877 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
879 pSMB->ParameterCount = cpu_to_le16(params);
880 pSMB->TotalParameterCount = pSMB->ParameterCount;
881 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
883 pSMB->hdr.smb_buf_length += byte_count;
884 pSMB->ByteCount = cpu_to_le16(byte_count);
885 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
886 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
888 cFYI(1, ("Posix delete returned %d", rc));
889 cifs_buf_release(pSMB);
891 cifs_stats_inc(&tcon->num_deletes);
900 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
901 const struct nls_table *nls_codepage, int remap)
903 DELETE_FILE_REQ *pSMB = NULL;
904 DELETE_FILE_RSP *pSMBr = NULL;
910 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
915 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
917 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
918 PATH_MAX, nls_codepage, remap);
919 name_len++; /* trailing null */
921 } else { /* BB improve check for buffer overruns BB */
922 name_len = strnlen(fileName, PATH_MAX);
923 name_len++; /* trailing null */
924 strncpy(pSMB->fileName, fileName, name_len);
926 pSMB->SearchAttributes =
927 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
928 pSMB->BufferFormat = 0x04;
929 pSMB->hdr.smb_buf_length += name_len + 1;
930 pSMB->ByteCount = cpu_to_le16(name_len + 1);
931 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
932 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
933 cifs_stats_inc(&tcon->num_deletes);
935 cFYI(1, ("Error in RMFile = %d", rc));
937 cifs_buf_release(pSMB);
945 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
946 const struct nls_table *nls_codepage, int remap)
948 DELETE_DIRECTORY_REQ *pSMB = NULL;
949 DELETE_DIRECTORY_RSP *pSMBr = NULL;
954 cFYI(1, ("In CIFSSMBRmDir"));
956 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
961 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
962 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
963 PATH_MAX, nls_codepage, remap);
964 name_len++; /* trailing null */
966 } else { /* BB improve check for buffer overruns BB */
967 name_len = strnlen(dirName, PATH_MAX);
968 name_len++; /* trailing null */
969 strncpy(pSMB->DirName, dirName, name_len);
972 pSMB->BufferFormat = 0x04;
973 pSMB->hdr.smb_buf_length += name_len + 1;
974 pSMB->ByteCount = cpu_to_le16(name_len + 1);
975 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
976 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
977 cifs_stats_inc(&tcon->num_rmdirs);
979 cFYI(1, ("Error in RMDir = %d", rc));
981 cifs_buf_release(pSMB);
988 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
989 const char *name, const struct nls_table *nls_codepage, int remap)
992 CREATE_DIRECTORY_REQ *pSMB = NULL;
993 CREATE_DIRECTORY_RSP *pSMBr = NULL;
997 cFYI(1, ("In CIFSSMBMkDir"));
999 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1004 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1005 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1006 PATH_MAX, nls_codepage, remap);
1007 name_len++; /* trailing null */
1009 } else { /* BB improve check for buffer overruns BB */
1010 name_len = strnlen(name, PATH_MAX);
1011 name_len++; /* trailing null */
1012 strncpy(pSMB->DirName, name, name_len);
1015 pSMB->BufferFormat = 0x04;
1016 pSMB->hdr.smb_buf_length += name_len + 1;
1017 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1018 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1019 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1020 cifs_stats_inc(&tcon->num_mkdirs);
1022 cFYI(1, ("Error in Mkdir = %d", rc));
1024 cifs_buf_release(pSMB);
1031 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1032 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1033 __u32 *pOplock, const char *name,
1034 const struct nls_table *nls_codepage, int remap)
1036 TRANSACTION2_SPI_REQ *pSMB = NULL;
1037 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1040 int bytes_returned = 0;
1041 __u16 params, param_offset, offset, byte_count, count;
1042 OPEN_PSX_REQ *pdata;
1043 OPEN_PSX_RSP *psx_rsp;
1045 cFYI(1, ("In POSIX Create"));
1047 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1052 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1054 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1055 PATH_MAX, nls_codepage, remap);
1056 name_len++; /* trailing null */
1058 } else { /* BB improve the check for buffer overruns BB */
1059 name_len = strnlen(name, PATH_MAX);
1060 name_len++; /* trailing null */
1061 strncpy(pSMB->FileName, name, name_len);
1064 params = 6 + name_len;
1065 count = sizeof(OPEN_PSX_REQ);
1066 pSMB->MaxParameterCount = cpu_to_le16(2);
1067 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1068 pSMB->MaxSetupCount = 0;
1072 pSMB->Reserved2 = 0;
1073 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1074 InformationLevel) - 4;
1075 offset = param_offset + params;
1076 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1077 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1078 pdata->Permissions = cpu_to_le64(mode);
1079 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1080 pdata->OpenFlags = cpu_to_le32(*pOplock);
1081 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1082 pSMB->DataOffset = cpu_to_le16(offset);
1083 pSMB->SetupCount = 1;
1084 pSMB->Reserved3 = 0;
1085 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1086 byte_count = 3 /* pad */ + params + count;
1088 pSMB->DataCount = cpu_to_le16(count);
1089 pSMB->ParameterCount = cpu_to_le16(params);
1090 pSMB->TotalDataCount = pSMB->DataCount;
1091 pSMB->TotalParameterCount = pSMB->ParameterCount;
1092 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1093 pSMB->Reserved4 = 0;
1094 pSMB->hdr.smb_buf_length += byte_count;
1095 pSMB->ByteCount = cpu_to_le16(byte_count);
1096 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1097 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1099 cFYI(1, ("Posix create returned %d", rc));
1100 goto psx_create_err;
1103 cFYI(1, ("copying inode info"));
1104 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1106 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1107 rc = -EIO; /* bad smb */
1108 goto psx_create_err;
1111 /* copy return information to pRetData */
1112 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1113 + le16_to_cpu(pSMBr->t2.DataOffset));
1115 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1117 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1118 /* Let caller know file was created so we can set the mode. */
1119 /* Do we care about the CreateAction in any other cases? */
1120 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1121 *pOplock |= CIFS_CREATE_ACTION;
1122 /* check to make sure response data is there */
1123 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1124 pRetData->Type = cpu_to_le32(-1); /* unknown */
1125 cFYI(DBG2, ("unknown type"));
1127 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1128 + sizeof(FILE_UNIX_BASIC_INFO)) {
1129 cERROR(1, ("Open response data too small"));
1130 pRetData->Type = cpu_to_le32(-1);
1131 goto psx_create_err;
1133 memcpy((char *) pRetData,
1134 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1135 sizeof(FILE_UNIX_BASIC_INFO));
1139 cifs_buf_release(pSMB);
1141 cifs_stats_inc(&tcon->num_mkdirs);
1149 static __u16 convert_disposition(int disposition)
1153 switch (disposition) {
1154 case FILE_SUPERSEDE:
1155 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1158 ofun = SMBOPEN_OAPPEND;
1161 ofun = SMBOPEN_OCREATE;
1164 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1166 case FILE_OVERWRITE:
1167 ofun = SMBOPEN_OTRUNC;
1169 case FILE_OVERWRITE_IF:
1170 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1173 cFYI(1, ("unknown disposition %d", disposition));
1174 ofun = SMBOPEN_OAPPEND; /* regular open */
1180 access_flags_to_smbopen_mode(const int access_flags)
1182 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1184 if (masked_flags == GENERIC_READ)
1185 return SMBOPEN_READ;
1186 else if (masked_flags == GENERIC_WRITE)
1187 return SMBOPEN_WRITE;
1189 /* just go for read/write */
1190 return SMBOPEN_READWRITE;
1194 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1195 const char *fileName, const int openDisposition,
1196 const int access_flags, const int create_options, __u16 *netfid,
1197 int *pOplock, FILE_ALL_INFO *pfile_info,
1198 const struct nls_table *nls_codepage, int remap)
1201 OPENX_REQ *pSMB = NULL;
1202 OPENX_RSP *pSMBr = NULL;
1208 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1213 pSMB->AndXCommand = 0xFF; /* none */
1215 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1216 count = 1; /* account for one byte pad to word boundary */
1218 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1219 fileName, PATH_MAX, nls_codepage, remap);
1220 name_len++; /* trailing null */
1222 } else { /* BB improve check for buffer overruns BB */
1223 count = 0; /* no pad */
1224 name_len = strnlen(fileName, PATH_MAX);
1225 name_len++; /* trailing null */
1226 strncpy(pSMB->fileName, fileName, name_len);
1228 if (*pOplock & REQ_OPLOCK)
1229 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1230 else if (*pOplock & REQ_BATCHOPLOCK)
1231 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1233 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1234 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1235 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1236 /* set file as system file if special file such
1237 as fifo and server expecting SFU style and
1238 no Unix extensions */
1240 if (create_options & CREATE_OPTION_SPECIAL)
1241 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1242 else /* BB FIXME BB */
1243 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1245 if (create_options & CREATE_OPTION_READONLY)
1246 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1249 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1250 CREATE_OPTIONS_MASK); */
1251 /* BB FIXME END BB */
1253 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1254 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1256 pSMB->hdr.smb_buf_length += count;
1258 pSMB->ByteCount = cpu_to_le16(count);
1259 /* long_op set to 1 to allow for oplock break timeouts */
1260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1261 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1262 cifs_stats_inc(&tcon->num_opens);
1264 cFYI(1, ("Error in Open = %d", rc));
1266 /* BB verify if wct == 15 */
1268 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1270 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1271 /* Let caller know file was created so we can set the mode. */
1272 /* Do we care about the CreateAction in any other cases? */
1274 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1275 *pOplock |= CIFS_CREATE_ACTION; */
1279 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1280 pfile_info->LastAccessTime = 0; /* BB fixme */
1281 pfile_info->LastWriteTime = 0; /* BB fixme */
1282 pfile_info->ChangeTime = 0; /* BB fixme */
1283 pfile_info->Attributes =
1284 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1285 /* the file_info buf is endian converted by caller */
1286 pfile_info->AllocationSize =
1287 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1288 pfile_info->EndOfFile = pfile_info->AllocationSize;
1289 pfile_info->NumberOfLinks = cpu_to_le32(1);
1290 pfile_info->DeletePending = 0;
1294 cifs_buf_release(pSMB);
1301 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1302 const char *fileName, const int openDisposition,
1303 const int access_flags, const int create_options, __u16 *netfid,
1304 int *pOplock, FILE_ALL_INFO *pfile_info,
1305 const struct nls_table *nls_codepage, int remap)
1308 OPEN_REQ *pSMB = NULL;
1309 OPEN_RSP *pSMBr = NULL;
1315 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1320 pSMB->AndXCommand = 0xFF; /* none */
1322 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1323 count = 1; /* account for one byte pad to word boundary */
1325 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1326 fileName, PATH_MAX, nls_codepage, remap);
1327 name_len++; /* trailing null */
1329 pSMB->NameLength = cpu_to_le16(name_len);
1330 } else { /* BB improve check for buffer overruns BB */
1331 count = 0; /* no pad */
1332 name_len = strnlen(fileName, PATH_MAX);
1333 name_len++; /* trailing null */
1334 pSMB->NameLength = cpu_to_le16(name_len);
1335 strncpy(pSMB->fileName, fileName, name_len);
1337 if (*pOplock & REQ_OPLOCK)
1338 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1339 else if (*pOplock & REQ_BATCHOPLOCK)
1340 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1341 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1342 pSMB->AllocationSize = 0;
1343 /* set file as system file if special file such
1344 as fifo and server expecting SFU style and
1345 no Unix extensions */
1346 if (create_options & CREATE_OPTION_SPECIAL)
1347 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1349 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1351 /* XP does not handle ATTR_POSIX_SEMANTICS */
1352 /* but it helps speed up case sensitive checks for other
1353 servers such as Samba */
1354 if (tcon->ses->capabilities & CAP_UNIX)
1355 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1357 if (create_options & CREATE_OPTION_READONLY)
1358 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1360 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1361 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1362 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1363 /* BB Expirement with various impersonation levels and verify */
1364 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1365 pSMB->SecurityFlags =
1366 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1369 pSMB->hdr.smb_buf_length += count;
1371 pSMB->ByteCount = cpu_to_le16(count);
1372 /* long_op set to 1 to allow for oplock break timeouts */
1373 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1374 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1375 cifs_stats_inc(&tcon->num_opens);
1377 cFYI(1, ("Error in Open = %d", rc));
1379 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1380 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1381 /* Let caller know file was created so we can set the mode. */
1382 /* Do we care about the CreateAction in any other cases? */
1383 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1384 *pOplock |= CIFS_CREATE_ACTION;
1386 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1387 36 /* CreationTime to Attributes */);
1388 /* the file_info buf is endian converted by caller */
1389 pfile_info->AllocationSize = pSMBr->AllocationSize;
1390 pfile_info->EndOfFile = pSMBr->EndOfFile;
1391 pfile_info->NumberOfLinks = cpu_to_le32(1);
1392 pfile_info->DeletePending = 0;
1396 cifs_buf_release(pSMB);
1403 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1404 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1405 char **buf, int *pbuf_type)
1408 READ_REQ *pSMB = NULL;
1409 READ_RSP *pSMBr = NULL;
1410 char *pReadData = NULL;
1412 int resp_buf_type = 0;
1415 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1416 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1419 wct = 10; /* old style read */
1420 if ((lseek >> 32) > 0) {
1421 /* can not handle this big offset for old */
1427 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1431 /* tcon and ses pointer are checked in smb_init */
1432 if (tcon->ses->server == NULL)
1433 return -ECONNABORTED;
1435 pSMB->AndXCommand = 0xFF; /* none */
1437 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1439 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1441 pSMB->Remaining = 0;
1442 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1443 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1445 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1447 /* old style read */
1448 struct smb_com_readx_req *pSMBW =
1449 (struct smb_com_readx_req *)pSMB;
1450 pSMBW->ByteCount = 0;
1453 iov[0].iov_base = (char *)pSMB;
1454 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1455 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1456 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1457 cifs_stats_inc(&tcon->num_reads);
1458 pSMBr = (READ_RSP *)iov[0].iov_base;
1460 cERROR(1, ("Send error in read = %d", rc));
1462 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1463 data_length = data_length << 16;
1464 data_length += le16_to_cpu(pSMBr->DataLength);
1465 *nbytes = data_length;
1467 /*check that DataLength would not go beyond end of SMB */
1468 if ((data_length > CIFSMaxBufSize)
1469 || (data_length > count)) {
1470 cFYI(1, ("bad length %d for count %d",
1471 data_length, count));
1475 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1476 le16_to_cpu(pSMBr->DataOffset);
1477 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1478 cERROR(1,("Faulting on read rc = %d",rc));
1480 }*/ /* can not use copy_to_user when using page cache*/
1482 memcpy(*buf, pReadData, data_length);
1486 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1488 if (resp_buf_type == CIFS_SMALL_BUFFER)
1489 cifs_small_buf_release(iov[0].iov_base);
1490 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1491 cifs_buf_release(iov[0].iov_base);
1492 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1493 /* return buffer to caller to free */
1494 *buf = iov[0].iov_base;
1495 if (resp_buf_type == CIFS_SMALL_BUFFER)
1496 *pbuf_type = CIFS_SMALL_BUFFER;
1497 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1498 *pbuf_type = CIFS_LARGE_BUFFER;
1499 } /* else no valid buffer on return - leave as null */
1501 /* Note: On -EAGAIN error only caller can retry on handle based calls
1502 since file handle passed in no longer valid */
1508 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1509 const int netfid, const unsigned int count,
1510 const __u64 offset, unsigned int *nbytes, const char *buf,
1511 const char __user *ubuf, const int long_op)
1514 WRITE_REQ *pSMB = NULL;
1515 WRITE_RSP *pSMBr = NULL;
1516 int bytes_returned, wct;
1520 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1521 if (tcon->ses == NULL)
1522 return -ECONNABORTED;
1524 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1528 if ((offset >> 32) > 0) {
1529 /* can not handle big offset for old srv */
1534 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1538 /* tcon and ses pointer are checked in smb_init */
1539 if (tcon->ses->server == NULL)
1540 return -ECONNABORTED;
1542 pSMB->AndXCommand = 0xFF; /* none */
1544 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1546 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1548 pSMB->Reserved = 0xFFFFFFFF;
1549 pSMB->WriteMode = 0;
1550 pSMB->Remaining = 0;
1552 /* Can increase buffer size if buffer is big enough in some cases ie we
1553 can send more if LARGE_WRITE_X capability returned by the server and if
1554 our buffer is big enough or if we convert to iovecs on socket writes
1555 and eliminate the copy to the CIFS buffer */
1556 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1557 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1559 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1563 if (bytes_sent > count)
1566 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1568 memcpy(pSMB->Data, buf, bytes_sent);
1570 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1571 cifs_buf_release(pSMB);
1574 } else if (count != 0) {
1576 cifs_buf_release(pSMB);
1578 } /* else setting file size with write of zero bytes */
1580 byte_count = bytes_sent + 1; /* pad */
1581 else /* wct == 12 */
1582 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1584 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1585 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1586 pSMB->hdr.smb_buf_length += byte_count;
1589 pSMB->ByteCount = cpu_to_le16(byte_count);
1590 else { /* old style write has byte count 4 bytes earlier
1592 struct smb_com_writex_req *pSMBW =
1593 (struct smb_com_writex_req *)pSMB;
1594 pSMBW->ByteCount = cpu_to_le16(byte_count);
1597 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1598 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1599 cifs_stats_inc(&tcon->num_writes);
1601 cFYI(1, ("Send error in write = %d", rc));
1604 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1605 *nbytes = (*nbytes) << 16;
1606 *nbytes += le16_to_cpu(pSMBr->Count);
1609 cifs_buf_release(pSMB);
1611 /* Note: On -EAGAIN error only caller can retry on handle based calls
1612 since file handle passed in no longer valid */
1618 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1619 const int netfid, const unsigned int count,
1620 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1621 int n_vec, const int long_op)
1624 WRITE_REQ *pSMB = NULL;
1627 int resp_buf_type = 0;
1629 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1631 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1635 if ((offset >> 32) > 0) {
1636 /* can not handle big offset for old srv */
1640 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1643 /* tcon and ses pointer are checked in smb_init */
1644 if (tcon->ses->server == NULL)
1645 return -ECONNABORTED;
1647 pSMB->AndXCommand = 0xFF; /* none */
1649 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1651 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1652 pSMB->Reserved = 0xFFFFFFFF;
1653 pSMB->WriteMode = 0;
1654 pSMB->Remaining = 0;
1657 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1659 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1660 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1661 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1663 pSMB->hdr.smb_buf_length += count+1;
1664 else /* wct == 12 */
1665 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1667 pSMB->ByteCount = cpu_to_le16(count + 1);
1668 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1669 struct smb_com_writex_req *pSMBW =
1670 (struct smb_com_writex_req *)pSMB;
1671 pSMBW->ByteCount = cpu_to_le16(count + 5);
1673 iov[0].iov_base = pSMB;
1675 iov[0].iov_len = smb_hdr_len + 4;
1676 else /* wct == 12 pad bigger by four bytes */
1677 iov[0].iov_len = smb_hdr_len + 8;
1680 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1682 cifs_stats_inc(&tcon->num_writes);
1684 cFYI(1, ("Send error Write2 = %d", rc));
1686 } else if (resp_buf_type == 0) {
1687 /* presumably this can not happen, but best to be safe */
1691 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1692 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1693 *nbytes = (*nbytes) << 16;
1694 *nbytes += le16_to_cpu(pSMBr->Count);
1697 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1698 if (resp_buf_type == CIFS_SMALL_BUFFER)
1699 cifs_small_buf_release(iov[0].iov_base);
1700 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1701 cifs_buf_release(iov[0].iov_base);
1703 /* Note: On -EAGAIN error only caller can retry on handle based calls
1704 since file handle passed in no longer valid */
1711 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1712 const __u16 smb_file_id, const __u64 len,
1713 const __u64 offset, const __u32 numUnlock,
1714 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1717 LOCK_REQ *pSMB = NULL;
1718 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1723 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1724 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1729 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1730 timeout = CIFS_ASYNC_OP; /* no response expected */
1732 } else if (waitFlag) {
1733 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1734 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1739 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1740 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1741 pSMB->LockType = lockType;
1742 pSMB->AndXCommand = 0xFF; /* none */
1743 pSMB->Fid = smb_file_id; /* netfid stays le */
1745 if ((numLock != 0) || (numUnlock != 0)) {
1746 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1747 /* BB where to store pid high? */
1748 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1749 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1750 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1751 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1752 count = sizeof(LOCKING_ANDX_RANGE);
1757 pSMB->hdr.smb_buf_length += count;
1758 pSMB->ByteCount = cpu_to_le16(count);
1761 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1762 (struct smb_hdr *) pSMB, &bytes_returned);
1763 cifs_small_buf_release(pSMB);
1765 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1767 /* SMB buffer freed by function above */
1769 cifs_stats_inc(&tcon->num_locks);
1771 cFYI(1, ("Send error in Lock = %d", rc));
1773 /* Note: On -EAGAIN error only caller can retry on handle based calls
1774 since file handle passed in no longer valid */
1779 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1780 const __u16 smb_file_id, const int get_flag, const __u64 len,
1781 struct file_lock *pLockData, const __u16 lock_type,
1782 const bool waitFlag)
1784 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1785 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1786 struct cifs_posix_lock *parm_data;
1789 int bytes_returned = 0;
1790 int resp_buf_type = 0;
1791 __u16 params, param_offset, offset, byte_count, count;
1794 cFYI(1, ("Posix Lock"));
1796 if (pLockData == NULL)
1799 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1804 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1807 pSMB->MaxSetupCount = 0;
1810 pSMB->Reserved2 = 0;
1811 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1812 offset = param_offset + params;
1814 count = sizeof(struct cifs_posix_lock);
1815 pSMB->MaxParameterCount = cpu_to_le16(2);
1816 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1817 pSMB->SetupCount = 1;
1818 pSMB->Reserved3 = 0;
1820 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1822 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1823 byte_count = 3 /* pad */ + params + count;
1824 pSMB->DataCount = cpu_to_le16(count);
1825 pSMB->ParameterCount = cpu_to_le16(params);
1826 pSMB->TotalDataCount = pSMB->DataCount;
1827 pSMB->TotalParameterCount = pSMB->ParameterCount;
1828 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1829 parm_data = (struct cifs_posix_lock *)
1830 (((char *) &pSMB->hdr.Protocol) + offset);
1832 parm_data->lock_type = cpu_to_le16(lock_type);
1834 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1835 parm_data->lock_flags = cpu_to_le16(1);
1836 pSMB->Timeout = cpu_to_le32(-1);
1840 parm_data->pid = cpu_to_le32(current->tgid);
1841 parm_data->start = cpu_to_le64(pLockData->fl_start);
1842 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1844 pSMB->DataOffset = cpu_to_le16(offset);
1845 pSMB->Fid = smb_file_id;
1846 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1847 pSMB->Reserved4 = 0;
1848 pSMB->hdr.smb_buf_length += byte_count;
1849 pSMB->ByteCount = cpu_to_le16(byte_count);
1851 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1852 (struct smb_hdr *) pSMBr, &bytes_returned);
1854 iov[0].iov_base = (char *)pSMB;
1855 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1856 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1857 &resp_buf_type, timeout);
1858 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1859 not try to free it twice below on exit */
1860 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1864 cFYI(1, ("Send error in Posix Lock = %d", rc));
1865 } else if (get_flag) {
1866 /* lock structure can be returned on get */
1869 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1871 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1872 rc = -EIO; /* bad smb */
1875 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1876 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1877 if (data_count < sizeof(struct cifs_posix_lock)) {
1881 parm_data = (struct cifs_posix_lock *)
1882 ((char *)&pSMBr->hdr.Protocol + data_offset);
1883 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1884 pLockData->fl_type = F_UNLCK;
1889 cifs_small_buf_release(pSMB);
1891 if (resp_buf_type == CIFS_SMALL_BUFFER)
1892 cifs_small_buf_release(iov[0].iov_base);
1893 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1894 cifs_buf_release(iov[0].iov_base);
1896 /* Note: On -EAGAIN error only caller can retry on handle based calls
1897 since file handle passed in no longer valid */
1904 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1907 CLOSE_REQ *pSMB = NULL;
1908 cFYI(1, ("In CIFSSMBClose"));
1910 /* do not retry on dead session on close */
1911 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1917 pSMB->FileID = (__u16) smb_file_id;
1918 pSMB->LastWriteTime = 0xFFFFFFFF;
1919 pSMB->ByteCount = 0;
1920 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1921 cifs_stats_inc(&tcon->num_closes);
1924 /* EINTR is expected when user ctl-c to kill app */
1925 cERROR(1, ("Send error in Close = %d", rc));
1929 /* Since session is dead, file will be closed on server already */
1937 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1938 const char *fromName, const char *toName,
1939 const struct nls_table *nls_codepage, int remap)
1942 RENAME_REQ *pSMB = NULL;
1943 RENAME_RSP *pSMBr = NULL;
1945 int name_len, name_len2;
1948 cFYI(1, ("In CIFSSMBRename"));
1950 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1955 pSMB->BufferFormat = 0x04;
1956 pSMB->SearchAttributes =
1957 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1962 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1963 PATH_MAX, nls_codepage, remap);
1964 name_len++; /* trailing null */
1966 pSMB->OldFileName[name_len] = 0x04; /* pad */
1967 /* protocol requires ASCII signature byte on Unicode string */
1968 pSMB->OldFileName[name_len + 1] = 0x00;
1970 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1971 toName, PATH_MAX, nls_codepage, remap);
1972 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1973 name_len2 *= 2; /* convert to bytes */
1974 } else { /* BB improve the check for buffer overruns BB */
1975 name_len = strnlen(fromName, PATH_MAX);
1976 name_len++; /* trailing null */
1977 strncpy(pSMB->OldFileName, fromName, name_len);
1978 name_len2 = strnlen(toName, PATH_MAX);
1979 name_len2++; /* trailing null */
1980 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1981 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1982 name_len2++; /* trailing null */
1983 name_len2++; /* signature byte */
1986 count = 1 /* 1st signature byte */ + name_len + name_len2;
1987 pSMB->hdr.smb_buf_length += count;
1988 pSMB->ByteCount = cpu_to_le16(count);
1990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1992 cifs_stats_inc(&tcon->num_renames);
1994 cFYI(1, ("Send error in rename = %d", rc));
1996 cifs_buf_release(pSMB);
2004 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2005 int netfid, const char *target_name,
2006 const struct nls_table *nls_codepage, int remap)
2008 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2009 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2010 struct set_file_rename *rename_info;
2012 char dummy_string[30];
2014 int bytes_returned = 0;
2016 __u16 params, param_offset, offset, count, byte_count;
2018 cFYI(1, ("Rename to File by handle"));
2019 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2025 pSMB->MaxSetupCount = 0;
2029 pSMB->Reserved2 = 0;
2030 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2031 offset = param_offset + params;
2033 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2034 rename_info = (struct set_file_rename *) data_offset;
2035 pSMB->MaxParameterCount = cpu_to_le16(2);
2036 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2037 pSMB->SetupCount = 1;
2038 pSMB->Reserved3 = 0;
2039 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2040 byte_count = 3 /* pad */ + params;
2041 pSMB->ParameterCount = cpu_to_le16(params);
2042 pSMB->TotalParameterCount = pSMB->ParameterCount;
2043 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2044 pSMB->DataOffset = cpu_to_le16(offset);
2045 /* construct random name ".cifs_tmp<inodenum><mid>" */
2046 rename_info->overwrite = cpu_to_le32(1);
2047 rename_info->root_fid = 0;
2048 /* unicode only call */
2049 if (target_name == NULL) {
2050 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2051 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2052 dummy_string, 24, nls_codepage, remap);
2054 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2055 target_name, PATH_MAX, nls_codepage,
2058 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2059 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2060 byte_count += count;
2061 pSMB->DataCount = cpu_to_le16(count);
2062 pSMB->TotalDataCount = pSMB->DataCount;
2064 pSMB->InformationLevel =
2065 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2066 pSMB->Reserved4 = 0;
2067 pSMB->hdr.smb_buf_length += byte_count;
2068 pSMB->ByteCount = cpu_to_le16(byte_count);
2069 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2070 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2071 cifs_stats_inc(&pTcon->num_t2renames);
2073 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2075 cifs_buf_release(pSMB);
2077 /* Note: On -EAGAIN error only caller can retry on handle based calls
2078 since file handle passed in no longer valid */
2084 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2085 const __u16 target_tid, const char *toName, const int flags,
2086 const struct nls_table *nls_codepage, int remap)
2089 COPY_REQ *pSMB = NULL;
2090 COPY_RSP *pSMBr = NULL;
2092 int name_len, name_len2;
2095 cFYI(1, ("In CIFSSMBCopy"));
2097 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2102 pSMB->BufferFormat = 0x04;
2103 pSMB->Tid2 = target_tid;
2105 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2107 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2108 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2109 fromName, PATH_MAX, nls_codepage,
2111 name_len++; /* trailing null */
2113 pSMB->OldFileName[name_len] = 0x04; /* pad */
2114 /* protocol requires ASCII signature byte on Unicode string */
2115 pSMB->OldFileName[name_len + 1] = 0x00;
2117 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2118 toName, PATH_MAX, nls_codepage, remap);
2119 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2120 name_len2 *= 2; /* convert to bytes */
2121 } else { /* BB improve the check for buffer overruns BB */
2122 name_len = strnlen(fromName, PATH_MAX);
2123 name_len++; /* trailing null */
2124 strncpy(pSMB->OldFileName, fromName, name_len);
2125 name_len2 = strnlen(toName, PATH_MAX);
2126 name_len2++; /* trailing null */
2127 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2128 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2129 name_len2++; /* trailing null */
2130 name_len2++; /* signature byte */
2133 count = 1 /* 1st signature byte */ + name_len + name_len2;
2134 pSMB->hdr.smb_buf_length += count;
2135 pSMB->ByteCount = cpu_to_le16(count);
2137 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2138 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2140 cFYI(1, ("Send error in copy = %d with %d files copied",
2141 rc, le16_to_cpu(pSMBr->CopyCount)));
2143 cifs_buf_release(pSMB);
2152 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2153 const char *fromName, const char *toName,
2154 const struct nls_table *nls_codepage)
2156 TRANSACTION2_SPI_REQ *pSMB = NULL;
2157 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2160 int name_len_target;
2162 int bytes_returned = 0;
2163 __u16 params, param_offset, offset, byte_count;
2165 cFYI(1, ("In Symlink Unix style"));
2167 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2172 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2174 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2175 /* find define for this maxpathcomponent */
2177 name_len++; /* trailing null */
2180 } else { /* BB improve the check for buffer overruns BB */
2181 name_len = strnlen(fromName, PATH_MAX);
2182 name_len++; /* trailing null */
2183 strncpy(pSMB->FileName, fromName, name_len);
2185 params = 6 + name_len;
2186 pSMB->MaxSetupCount = 0;
2190 pSMB->Reserved2 = 0;
2191 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2192 InformationLevel) - 4;
2193 offset = param_offset + params;
2195 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2196 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2198 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2199 /* find define for this maxpathcomponent */
2201 name_len_target++; /* trailing null */
2202 name_len_target *= 2;
2203 } else { /* BB improve the check for buffer overruns BB */
2204 name_len_target = strnlen(toName, PATH_MAX);
2205 name_len_target++; /* trailing null */
2206 strncpy(data_offset, toName, name_len_target);
2209 pSMB->MaxParameterCount = cpu_to_le16(2);
2210 /* BB find exact max on data count below from sess */
2211 pSMB->MaxDataCount = cpu_to_le16(1000);
2212 pSMB->SetupCount = 1;
2213 pSMB->Reserved3 = 0;
2214 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2215 byte_count = 3 /* pad */ + params + name_len_target;
2216 pSMB->DataCount = cpu_to_le16(name_len_target);
2217 pSMB->ParameterCount = cpu_to_le16(params);
2218 pSMB->TotalDataCount = pSMB->DataCount;
2219 pSMB->TotalParameterCount = pSMB->ParameterCount;
2220 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2221 pSMB->DataOffset = cpu_to_le16(offset);
2222 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2223 pSMB->Reserved4 = 0;
2224 pSMB->hdr.smb_buf_length += byte_count;
2225 pSMB->ByteCount = cpu_to_le16(byte_count);
2226 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2227 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2228 cifs_stats_inc(&tcon->num_symlinks);
2230 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2232 cifs_buf_release(pSMB);
2235 goto createSymLinkRetry;
2241 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2242 const char *fromName, const char *toName,
2243 const struct nls_table *nls_codepage, int remap)
2245 TRANSACTION2_SPI_REQ *pSMB = NULL;
2246 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2249 int name_len_target;
2251 int bytes_returned = 0;
2252 __u16 params, param_offset, offset, byte_count;
2254 cFYI(1, ("In Create Hard link Unix style"));
2255 createHardLinkRetry:
2256 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2261 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2262 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2263 PATH_MAX, nls_codepage, remap);
2264 name_len++; /* trailing null */
2267 } else { /* BB improve the check for buffer overruns BB */
2268 name_len = strnlen(toName, PATH_MAX);
2269 name_len++; /* trailing null */
2270 strncpy(pSMB->FileName, toName, name_len);
2272 params = 6 + name_len;
2273 pSMB->MaxSetupCount = 0;
2277 pSMB->Reserved2 = 0;
2278 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2279 InformationLevel) - 4;
2280 offset = param_offset + params;
2282 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2283 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2285 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2286 nls_codepage, remap);
2287 name_len_target++; /* trailing null */
2288 name_len_target *= 2;
2289 } else { /* BB improve the check for buffer overruns BB */
2290 name_len_target = strnlen(fromName, PATH_MAX);
2291 name_len_target++; /* trailing null */
2292 strncpy(data_offset, fromName, name_len_target);
2295 pSMB->MaxParameterCount = cpu_to_le16(2);
2296 /* BB find exact max on data count below from sess*/
2297 pSMB->MaxDataCount = cpu_to_le16(1000);
2298 pSMB->SetupCount = 1;
2299 pSMB->Reserved3 = 0;
2300 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2301 byte_count = 3 /* pad */ + params + name_len_target;
2302 pSMB->ParameterCount = cpu_to_le16(params);
2303 pSMB->TotalParameterCount = pSMB->ParameterCount;
2304 pSMB->DataCount = cpu_to_le16(name_len_target);
2305 pSMB->TotalDataCount = pSMB->DataCount;
2306 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2307 pSMB->DataOffset = cpu_to_le16(offset);
2308 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2309 pSMB->Reserved4 = 0;
2310 pSMB->hdr.smb_buf_length += byte_count;
2311 pSMB->ByteCount = cpu_to_le16(byte_count);
2312 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2313 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2314 cifs_stats_inc(&tcon->num_hardlinks);
2316 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2318 cifs_buf_release(pSMB);
2320 goto createHardLinkRetry;
2326 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2327 const char *fromName, const char *toName,
2328 const struct nls_table *nls_codepage, int remap)
2331 NT_RENAME_REQ *pSMB = NULL;
2332 RENAME_RSP *pSMBr = NULL;
2334 int name_len, name_len2;
2337 cFYI(1, ("In CIFSCreateHardLink"));
2338 winCreateHardLinkRetry:
2340 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2345 pSMB->SearchAttributes =
2346 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2348 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2349 pSMB->ClusterCount = 0;
2351 pSMB->BufferFormat = 0x04;
2353 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2355 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2356 PATH_MAX, nls_codepage, remap);
2357 name_len++; /* trailing null */
2359 pSMB->OldFileName[name_len] = 0; /* pad */
2360 pSMB->OldFileName[name_len + 1] = 0x04;
2362 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2363 toName, PATH_MAX, nls_codepage, remap);
2364 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2365 name_len2 *= 2; /* convert to bytes */
2366 } else { /* BB improve the check for buffer overruns BB */
2367 name_len = strnlen(fromName, PATH_MAX);
2368 name_len++; /* trailing null */
2369 strncpy(pSMB->OldFileName, fromName, name_len);
2370 name_len2 = strnlen(toName, PATH_MAX);
2371 name_len2++; /* trailing null */
2372 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2373 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2374 name_len2++; /* trailing null */
2375 name_len2++; /* signature byte */
2378 count = 1 /* string type byte */ + name_len + name_len2;
2379 pSMB->hdr.smb_buf_length += count;
2380 pSMB->ByteCount = cpu_to_le16(count);
2382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2384 cifs_stats_inc(&tcon->num_hardlinks);
2386 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2388 cifs_buf_release(pSMB);
2390 goto winCreateHardLinkRetry;
2396 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2397 const unsigned char *searchName,
2398 char *symlinkinfo, const int buflen,
2399 const struct nls_table *nls_codepage)
2401 /* SMB_QUERY_FILE_UNIX_LINK */
2402 TRANSACTION2_QPI_REQ *pSMB = NULL;
2403 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2407 __u16 params, byte_count;
2409 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2412 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2417 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2419 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2420 PATH_MAX, nls_codepage);
2421 name_len++; /* trailing null */
2423 } else { /* BB improve the check for buffer overruns BB */
2424 name_len = strnlen(searchName, PATH_MAX);
2425 name_len++; /* trailing null */
2426 strncpy(pSMB->FileName, searchName, name_len);
2429 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2430 pSMB->TotalDataCount = 0;
2431 pSMB->MaxParameterCount = cpu_to_le16(2);
2432 /* BB find exact max data count below from sess structure BB */
2433 pSMB->MaxDataCount = cpu_to_le16(4000);
2434 pSMB->MaxSetupCount = 0;
2438 pSMB->Reserved2 = 0;
2439 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2440 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2441 pSMB->DataCount = 0;
2442 pSMB->DataOffset = 0;
2443 pSMB->SetupCount = 1;
2444 pSMB->Reserved3 = 0;
2445 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2446 byte_count = params + 1 /* pad */ ;
2447 pSMB->TotalParameterCount = cpu_to_le16(params);
2448 pSMB->ParameterCount = pSMB->TotalParameterCount;
2449 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2450 pSMB->Reserved4 = 0;
2451 pSMB->hdr.smb_buf_length += byte_count;
2452 pSMB->ByteCount = cpu_to_le16(byte_count);
2454 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2455 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2457 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2459 /* decode response */
2461 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2462 if (rc || (pSMBr->ByteCount < 2))
2463 /* BB also check enough total bytes returned */
2464 rc = -EIO; /* bad smb */
2466 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2467 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2469 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2470 name_len = UniStrnlen((wchar_t *) ((char *)
2471 &pSMBr->hdr.Protocol + data_offset),
2472 min_t(const int, buflen, count) / 2);
2473 /* BB FIXME investigate remapping reserved chars here */
2474 cifs_strfromUCS_le(symlinkinfo,
2475 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2477 name_len, nls_codepage);
2479 strncpy(symlinkinfo,
2480 (char *) &pSMBr->hdr.Protocol +
2482 min_t(const int, buflen, count));
2484 symlinkinfo[buflen] = 0;
2485 /* just in case so calling code does not go off the end of buffer */
2488 cifs_buf_release(pSMB);
2490 goto querySymLinkRetry;
2494 #ifdef CONFIG_CIFS_EXPERIMENTAL
2495 /* Initialize NT TRANSACT SMB into small smb request buffer.
2496 This assumes that all NT TRANSACTS that we init here have
2497 total parm and data under about 400 bytes (to fit in small cifs
2498 buffer size), which is the case so far, it easily fits. NB:
2499 Setup words themselves and ByteCount
2500 MaxSetupCount (size of returned setup area) and
2501 MaxParameterCount (returned parms size) must be set by caller */
2503 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2504 const int parm_len, struct cifsTconInfo *tcon,
2509 struct smb_com_ntransact_req *pSMB;
2511 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2515 *ret_buf = (void *)pSMB;
2517 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2518 pSMB->TotalDataCount = 0;
2519 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2520 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2521 pSMB->ParameterCount = pSMB->TotalParameterCount;
2522 pSMB->DataCount = pSMB->TotalDataCount;
2523 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2524 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2525 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2526 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2527 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2528 pSMB->SubCommand = cpu_to_le16(sub_command);
2533 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2534 __u32 *pparmlen, __u32 *pdatalen)
2537 __u32 data_count, data_offset, parm_count, parm_offset;
2538 struct smb_com_ntransact_rsp *pSMBr;
2546 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2548 /* ByteCount was converted from little endian in SendReceive */
2549 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2550 (char *)&pSMBr->ByteCount;
2552 data_offset = le32_to_cpu(pSMBr->DataOffset);
2553 data_count = le32_to_cpu(pSMBr->DataCount);
2554 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2555 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2557 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2558 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2560 /* should we also check that parm and data areas do not overlap? */
2561 if (*ppparm > end_of_smb) {
2562 cFYI(1, ("parms start after end of smb"));
2564 } else if (parm_count + *ppparm > end_of_smb) {
2565 cFYI(1, ("parm end after end of smb"));
2567 } else if (*ppdata > end_of_smb) {
2568 cFYI(1, ("data starts after end of smb"));
2570 } else if (data_count + *ppdata > end_of_smb) {
2571 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2572 *ppdata, data_count, (data_count + *ppdata),
2573 end_of_smb, pSMBr));
2575 } else if (parm_count + data_count > pSMBr->ByteCount) {
2576 cFYI(1, ("parm count and data count larger than SMB"));
2579 *pdatalen = data_count;
2580 *pparmlen = parm_count;
2583 #endif /* CIFS_EXPERIMENTAL */
2586 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2587 const unsigned char *searchName,
2588 char *symlinkinfo, const int buflen, __u16 fid,
2589 const struct nls_table *nls_codepage)
2594 struct smb_com_transaction_ioctl_req *pSMB;
2595 struct smb_com_transaction_ioctl_rsp *pSMBr;
2597 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2598 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2603 pSMB->TotalParameterCount = 0 ;
2604 pSMB->TotalDataCount = 0;
2605 pSMB->MaxParameterCount = cpu_to_le32(2);
2606 /* BB find exact data count max from sess structure BB */
2607 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2608 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2609 pSMB->MaxSetupCount = 4;
2611 pSMB->ParameterOffset = 0;
2612 pSMB->DataCount = 0;
2613 pSMB->DataOffset = 0;
2614 pSMB->SetupCount = 4;
2615 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2616 pSMB->ParameterCount = pSMB->TotalParameterCount;
2617 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2618 pSMB->IsFsctl = 1; /* FSCTL */
2619 pSMB->IsRootFlag = 0;
2620 pSMB->Fid = fid; /* file handle always le */
2621 pSMB->ByteCount = 0;
2623 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2624 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2626 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2627 } else { /* decode response */
2628 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2629 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2630 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2631 /* BB also check enough total bytes returned */
2632 rc = -EIO; /* bad smb */
2634 if (data_count && (data_count < 2048)) {
2635 char *end_of_smb = 2 /* sizeof byte count */ +
2637 (char *)&pSMBr->ByteCount;
2639 struct reparse_data *reparse_buf =
2640 (struct reparse_data *)
2641 ((char *)&pSMBr->hdr.Protocol
2643 if ((char *)reparse_buf >= end_of_smb) {
2647 if ((reparse_buf->LinkNamesBuf +
2648 reparse_buf->TargetNameOffset +
2649 reparse_buf->TargetNameLen) >
2651 cFYI(1, ("reparse buf beyond SMB"));
2656 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2657 name_len = UniStrnlen((wchar_t *)
2658 (reparse_buf->LinkNamesBuf +
2659 reparse_buf->TargetNameOffset),
2661 reparse_buf->TargetNameLen / 2));
2662 cifs_strfromUCS_le(symlinkinfo,
2663 (__le16 *) (reparse_buf->LinkNamesBuf +
2664 reparse_buf->TargetNameOffset),
2665 name_len, nls_codepage);
2666 } else { /* ASCII names */
2667 strncpy(symlinkinfo,
2668 reparse_buf->LinkNamesBuf +
2669 reparse_buf->TargetNameOffset,
2670 min_t(const int, buflen,
2671 reparse_buf->TargetNameLen));
2675 cFYI(1, ("Invalid return data count on "
2676 "get reparse info ioctl"));
2678 symlinkinfo[buflen] = 0; /* just in case so the caller
2679 does not go off the end of the buffer */
2680 cFYI(1, ("readlink result - %s", symlinkinfo));
2684 cifs_buf_release(pSMB);
2686 /* Note: On -EAGAIN error only caller can retry on handle based calls
2687 since file handle passed in no longer valid */
2692 #ifdef CONFIG_CIFS_POSIX
2694 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2695 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2696 struct cifs_posix_ace *cifs_ace)
2698 /* u8 cifs fields do not need le conversion */
2699 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2700 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2701 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2702 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2707 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2708 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2709 const int acl_type, const int size_of_data_area)
2714 struct cifs_posix_ace *pACE;
2715 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2716 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2718 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2721 if (acl_type & ACL_TYPE_ACCESS) {
2722 count = le16_to_cpu(cifs_acl->access_entry_count);
2723 pACE = &cifs_acl->ace_array[0];
2724 size = sizeof(struct cifs_posix_acl);
2725 size += sizeof(struct cifs_posix_ace) * count;
2726 /* check if we would go beyond end of SMB */
2727 if (size_of_data_area < size) {
2728 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2729 size_of_data_area, size));
2732 } else if (acl_type & ACL_TYPE_DEFAULT) {
2733 count = le16_to_cpu(cifs_acl->access_entry_count);
2734 size = sizeof(struct cifs_posix_acl);
2735 size += sizeof(struct cifs_posix_ace) * count;
2736 /* skip past access ACEs to get to default ACEs */
2737 pACE = &cifs_acl->ace_array[count];
2738 count = le16_to_cpu(cifs_acl->default_entry_count);
2739 size += sizeof(struct cifs_posix_ace) * count;
2740 /* check if we would go beyond end of SMB */
2741 if (size_of_data_area < size)
2748 size = posix_acl_xattr_size(count);
2749 if ((buflen == 0) || (local_acl == NULL)) {
2750 /* used to query ACL EA size */
2751 } else if (size > buflen) {
2753 } else /* buffer big enough */ {
2754 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2755 for (i = 0; i < count ; i++) {
2756 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2763 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2764 const posix_acl_xattr_entry *local_ace)
2766 __u16 rc = 0; /* 0 = ACL converted ok */
2768 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2769 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2770 /* BB is there a better way to handle the large uid? */
2771 if (local_ace->e_id == cpu_to_le32(-1)) {
2772 /* Probably no need to le convert -1 on any arch but can not hurt */
2773 cifs_ace->cifs_uid = cpu_to_le64(-1);
2775 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2776 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2780 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2781 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2782 const int buflen, const int acl_type)
2785 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2786 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2790 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2793 count = posix_acl_xattr_count((size_t)buflen);
2794 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2796 count, buflen, le32_to_cpu(local_acl->a_version)));
2797 if (le32_to_cpu(local_acl->a_version) != 2) {
2798 cFYI(1, ("unknown POSIX ACL version %d",
2799 le32_to_cpu(local_acl->a_version)));
2802 cifs_acl->version = cpu_to_le16(1);
2803 if (acl_type == ACL_TYPE_ACCESS)
2804 cifs_acl->access_entry_count = cpu_to_le16(count);
2805 else if (acl_type == ACL_TYPE_DEFAULT)
2806 cifs_acl->default_entry_count = cpu_to_le16(count);
2808 cFYI(1, ("unknown ACL type %d", acl_type));
2811 for (i = 0; i < count; i++) {
2812 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2813 &local_acl->a_entries[i]);
2815 /* ACE not converted */
2820 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2821 rc += sizeof(struct cifs_posix_acl);
2822 /* BB add check to make sure ACL does not overflow SMB */
2828 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2829 const unsigned char *searchName,
2830 char *acl_inf, const int buflen, const int acl_type,
2831 const struct nls_table *nls_codepage, int remap)
2833 /* SMB_QUERY_POSIX_ACL */
2834 TRANSACTION2_QPI_REQ *pSMB = NULL;
2835 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2839 __u16 params, byte_count;
2841 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2844 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2849 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2851 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2852 PATH_MAX, nls_codepage, remap);
2853 name_len++; /* trailing null */
2855 pSMB->FileName[name_len] = 0;
2856 pSMB->FileName[name_len+1] = 0;
2857 } else { /* BB improve the check for buffer overruns BB */
2858 name_len = strnlen(searchName, PATH_MAX);
2859 name_len++; /* trailing null */
2860 strncpy(pSMB->FileName, searchName, name_len);
2863 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2864 pSMB->TotalDataCount = 0;
2865 pSMB->MaxParameterCount = cpu_to_le16(2);
2866 /* BB find exact max data count below from sess structure BB */
2867 pSMB->MaxDataCount = cpu_to_le16(4000);
2868 pSMB->MaxSetupCount = 0;
2872 pSMB->Reserved2 = 0;
2873 pSMB->ParameterOffset = cpu_to_le16(
2874 offsetof(struct smb_com_transaction2_qpi_req,
2875 InformationLevel) - 4);
2876 pSMB->DataCount = 0;
2877 pSMB->DataOffset = 0;
2878 pSMB->SetupCount = 1;
2879 pSMB->Reserved3 = 0;
2880 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2881 byte_count = params + 1 /* pad */ ;
2882 pSMB->TotalParameterCount = cpu_to_le16(params);
2883 pSMB->ParameterCount = pSMB->TotalParameterCount;
2884 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2885 pSMB->Reserved4 = 0;
2886 pSMB->hdr.smb_buf_length += byte_count;
2887 pSMB->ByteCount = cpu_to_le16(byte_count);
2889 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2890 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2891 cifs_stats_inc(&tcon->num_acl_get);
2893 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2895 /* decode response */
2897 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2898 if (rc || (pSMBr->ByteCount < 2))
2899 /* BB also check enough total bytes returned */
2900 rc = -EIO; /* bad smb */
2902 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2903 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2904 rc = cifs_copy_posix_acl(acl_inf,
2905 (char *)&pSMBr->hdr.Protocol+data_offset,
2906 buflen, acl_type, count);
2909 cifs_buf_release(pSMB);
2916 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2917 const unsigned char *fileName,
2918 const char *local_acl, const int buflen,
2920 const struct nls_table *nls_codepage, int remap)
2922 struct smb_com_transaction2_spi_req *pSMB = NULL;
2923 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2927 int bytes_returned = 0;
2928 __u16 params, byte_count, data_count, param_offset, offset;
2930 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2932 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2936 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2938 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2939 PATH_MAX, nls_codepage, remap);
2940 name_len++; /* trailing null */
2942 } else { /* BB improve the check for buffer overruns BB */
2943 name_len = strnlen(fileName, PATH_MAX);
2944 name_len++; /* trailing null */
2945 strncpy(pSMB->FileName, fileName, name_len);
2947 params = 6 + name_len;
2948 pSMB->MaxParameterCount = cpu_to_le16(2);
2949 /* BB find max SMB size from sess */
2950 pSMB->MaxDataCount = cpu_to_le16(1000);
2951 pSMB->MaxSetupCount = 0;
2955 pSMB->Reserved2 = 0;
2956 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2957 InformationLevel) - 4;
2958 offset = param_offset + params;
2959 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2960 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2962 /* convert to on the wire format for POSIX ACL */
2963 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2965 if (data_count == 0) {
2967 goto setACLerrorExit;
2969 pSMB->DataOffset = cpu_to_le16(offset);
2970 pSMB->SetupCount = 1;
2971 pSMB->Reserved3 = 0;
2972 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2973 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2974 byte_count = 3 /* pad */ + params + data_count;
2975 pSMB->DataCount = cpu_to_le16(data_count);
2976 pSMB->TotalDataCount = pSMB->DataCount;
2977 pSMB->ParameterCount = cpu_to_le16(params);
2978 pSMB->TotalParameterCount = pSMB->ParameterCount;
2979 pSMB->Reserved4 = 0;
2980 pSMB->hdr.smb_buf_length += byte_count;
2981 pSMB->ByteCount = cpu_to_le16(byte_count);
2982 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2983 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2985 cFYI(1, ("Set POSIX ACL returned %d", rc));
2988 cifs_buf_release(pSMB);
2994 /* BB fix tabs in this function FIXME BB */
2996 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2997 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3000 struct smb_t2_qfi_req *pSMB = NULL;
3001 struct smb_t2_qfi_rsp *pSMBr = NULL;
3003 __u16 params, byte_count;
3005 cFYI(1, ("In GetExtAttr"));
3010 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3015 params = 2 /* level */ + 2 /* fid */;
3016 pSMB->t2.TotalDataCount = 0;
3017 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3018 /* BB find exact max data count below from sess structure BB */
3019 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3020 pSMB->t2.MaxSetupCount = 0;
3021 pSMB->t2.Reserved = 0;
3023 pSMB->t2.Timeout = 0;
3024 pSMB->t2.Reserved2 = 0;
3025 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3027 pSMB->t2.DataCount = 0;
3028 pSMB->t2.DataOffset = 0;
3029 pSMB->t2.SetupCount = 1;
3030 pSMB->t2.Reserved3 = 0;
3031 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3032 byte_count = params + 1 /* pad */ ;
3033 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3034 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3035 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3038 pSMB->hdr.smb_buf_length += byte_count;
3039 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3041 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3042 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3044 cFYI(1, ("error %d in GetExtAttr", rc));
3046 /* decode response */
3047 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3048 if (rc || (pSMBr->ByteCount < 2))
3049 /* BB also check enough total bytes returned */
3050 /* If rc should we check for EOPNOSUPP and
3051 disable the srvino flag? or in caller? */
3052 rc = -EIO; /* bad smb */
3054 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3055 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3056 struct file_chattr_info *pfinfo;
3057 /* BB Do we need a cast or hash here ? */
3059 cFYI(1, ("Illegal size ret in GetExtAttr"));
3063 pfinfo = (struct file_chattr_info *)
3064 (data_offset + (char *) &pSMBr->hdr.Protocol);
3065 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3066 *pMask = le64_to_cpu(pfinfo->mask);
3070 cifs_buf_release(pSMB);
3072 goto GetExtAttrRetry;
3076 #endif /* CONFIG_POSIX */
3078 #ifdef CONFIG_CIFS_EXPERIMENTAL
3079 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3081 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3082 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3086 QUERY_SEC_DESC_REQ *pSMB;
3089 cFYI(1, ("GetCifsACL"));
3094 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3095 8 /* parm len */, tcon, (void **) &pSMB);
3099 pSMB->MaxParameterCount = cpu_to_le32(4);
3100 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3101 pSMB->MaxSetupCount = 0;
3102 pSMB->Fid = fid; /* file handle always le */
3103 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3105 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3106 pSMB->hdr.smb_buf_length += 11;
3107 iov[0].iov_base = (char *)pSMB;
3108 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3110 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3112 cifs_stats_inc(&tcon->num_acl_get);
3114 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3115 } else { /* decode response */
3119 struct smb_com_ntransact_rsp *pSMBr;
3122 /* validate_nttransact */
3123 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3124 &pdata, &parm_len, pbuflen);
3127 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3129 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3131 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3132 rc = -EIO; /* bad smb */
3137 /* BB check that data area is minimum length and as big as acl_len */
3139 acl_len = le32_to_cpu(*parm);
3140 if (acl_len != *pbuflen) {
3141 cERROR(1, ("acl length %d does not match %d",
3142 acl_len, *pbuflen));
3143 if (*pbuflen > acl_len)
3147 /* check if buffer is big enough for the acl
3148 header followed by the smallest SID */
3149 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3150 (*pbuflen >= 64 * 1024)) {
3151 cERROR(1, ("bad acl length %d", *pbuflen));
3155 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3156 if (*acl_inf == NULL) {
3160 memcpy(*acl_inf, pdata, *pbuflen);
3164 if (buf_type == CIFS_SMALL_BUFFER)
3165 cifs_small_buf_release(iov[0].iov_base);
3166 else if (buf_type == CIFS_LARGE_BUFFER)
3167 cifs_buf_release(iov[0].iov_base);
3168 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3173 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3174 struct cifs_ntsd *pntsd, __u32 acllen)
3176 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3178 int bytes_returned = 0;
3179 SET_SEC_DESC_REQ *pSMB = NULL;
3180 NTRANSACT_RSP *pSMBr = NULL;
3183 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3188 pSMB->MaxSetupCount = 0;
3192 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3193 data_count = acllen;
3194 data_offset = param_offset + param_count;
3195 byte_count = 3 /* pad */ + param_count;
3197 pSMB->DataCount = cpu_to_le32(data_count);
3198 pSMB->TotalDataCount = pSMB->DataCount;
3199 pSMB->MaxParameterCount = cpu_to_le32(4);
3200 pSMB->MaxDataCount = cpu_to_le32(16384);
3201 pSMB->ParameterCount = cpu_to_le32(param_count);
3202 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3203 pSMB->TotalParameterCount = pSMB->ParameterCount;
3204 pSMB->DataOffset = cpu_to_le32(data_offset);
3205 pSMB->SetupCount = 0;
3206 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3207 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3209 pSMB->Fid = fid; /* file handle always le */
3210 pSMB->Reserved2 = 0;
3211 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3213 if (pntsd && acllen) {
3214 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3217 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3220 pSMB->hdr.smb_buf_length += byte_count;
3222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3225 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3227 cFYI(1, ("Set CIFS ACL returned %d", rc));
3228 cifs_buf_release(pSMB);
3231 goto setCifsAclRetry;
3236 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3238 /* Legacy Query Path Information call for lookup to old servers such
3240 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3241 const unsigned char *searchName,
3242 FILE_ALL_INFO *pFinfo,
3243 const struct nls_table *nls_codepage, int remap)
3245 QUERY_INFORMATION_REQ *pSMB;
3246 QUERY_INFORMATION_RSP *pSMBr;
3251 cFYI(1, ("In SMBQPath path %s", searchName));
3253 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3258 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3260 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3261 PATH_MAX, nls_codepage, remap);
3262 name_len++; /* trailing null */
3265 name_len = strnlen(searchName, PATH_MAX);
3266 name_len++; /* trailing null */
3267 strncpy(pSMB->FileName, searchName, name_len);
3269 pSMB->BufferFormat = 0x04;
3270 name_len++; /* account for buffer type byte */
3271 pSMB->hdr.smb_buf_length += (__u16) name_len;
3272 pSMB->ByteCount = cpu_to_le16(name_len);
3274 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3275 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3277 cFYI(1, ("Send error in QueryInfo = %d", rc));
3278 } else if (pFinfo) {
3280 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3282 /* decode response */
3283 /* BB FIXME - add time zone adjustment BB */
3284 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3287 /* decode time fields */
3288 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3289 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3290 pFinfo->LastAccessTime = 0;
3291 pFinfo->AllocationSize =
3292 cpu_to_le64(le32_to_cpu(pSMBr->size));
3293 pFinfo->EndOfFile = pFinfo->AllocationSize;
3294 pFinfo->Attributes =
3295 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3297 rc = -EIO; /* bad buffer passed in */
3299 cifs_buf_release(pSMB);
3311 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3312 const unsigned char *searchName,
3313 FILE_ALL_INFO *pFindData,
3314 int legacy /* old style infolevel */,
3315 const struct nls_table *nls_codepage, int remap)
3317 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3318 TRANSACTION2_QPI_REQ *pSMB = NULL;
3319 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3323 __u16 params, byte_count;
3325 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3327 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3332 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3334 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3335 PATH_MAX, nls_codepage, remap);
3336 name_len++; /* trailing null */
3338 } else { /* BB improve the check for buffer overruns BB */
3339 name_len = strnlen(searchName, PATH_MAX);
3340 name_len++; /* trailing null */
3341 strncpy(pSMB->FileName, searchName, name_len);
3344 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3345 pSMB->TotalDataCount = 0;
3346 pSMB->MaxParameterCount = cpu_to_le16(2);
3347 /* BB find exact max SMB PDU from sess structure BB */
3348 pSMB->MaxDataCount = cpu_to_le16(4000);
3349 pSMB->MaxSetupCount = 0;
3353 pSMB->Reserved2 = 0;
3354 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3355 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3356 pSMB->DataCount = 0;
3357 pSMB->DataOffset = 0;
3358 pSMB->SetupCount = 1;
3359 pSMB->Reserved3 = 0;
3360 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3361 byte_count = params + 1 /* pad */ ;
3362 pSMB->TotalParameterCount = cpu_to_le16(params);
3363 pSMB->ParameterCount = pSMB->TotalParameterCount;
3365 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3367 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3368 pSMB->Reserved4 = 0;
3369 pSMB->hdr.smb_buf_length += byte_count;
3370 pSMB->ByteCount = cpu_to_le16(byte_count);
3372 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3373 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3375 cFYI(1, ("Send error in QPathInfo = %d", rc));
3376 } else { /* decode response */
3377 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3379 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3381 else if (!legacy && (pSMBr->ByteCount < 40))
3382 rc = -EIO; /* bad smb */
3383 else if (legacy && (pSMBr->ByteCount < 24))
3384 rc = -EIO; /* 24 or 26 expected but we do not read
3386 else if (pFindData) {
3388 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3390 /* On legacy responses we do not read the last field,
3391 EAsize, fortunately since it varies by subdialect and
3392 also note it differs on Set vs. Get, ie two bytes or 4
3393 bytes depending but we don't care here */
3395 size = sizeof(FILE_INFO_STANDARD);
3397 size = sizeof(FILE_ALL_INFO);
3398 memcpy((char *) pFindData,
3399 (char *) &pSMBr->hdr.Protocol +
3404 cifs_buf_release(pSMB);
3406 goto QPathInfoRetry;
3412 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3413 const unsigned char *searchName,
3414 FILE_UNIX_BASIC_INFO *pFindData,
3415 const struct nls_table *nls_codepage, int remap)
3417 /* SMB_QUERY_FILE_UNIX_BASIC */
3418 TRANSACTION2_QPI_REQ *pSMB = NULL;
3419 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3421 int bytes_returned = 0;
3423 __u16 params, byte_count;
3425 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3427 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3432 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3434 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3435 PATH_MAX, nls_codepage, remap);
3436 name_len++; /* trailing null */
3438 } else { /* BB improve the check for buffer overruns BB */
3439 name_len = strnlen(searchName, PATH_MAX);
3440 name_len++; /* trailing null */
3441 strncpy(pSMB->FileName, searchName, name_len);
3444 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3445 pSMB->TotalDataCount = 0;
3446 pSMB->MaxParameterCount = cpu_to_le16(2);
3447 /* BB find exact max SMB PDU from sess structure BB */
3448 pSMB->MaxDataCount = cpu_to_le16(4000);
3449 pSMB->MaxSetupCount = 0;
3453 pSMB->Reserved2 = 0;
3454 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3455 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3456 pSMB->DataCount = 0;
3457 pSMB->DataOffset = 0;
3458 pSMB->SetupCount = 1;
3459 pSMB->Reserved3 = 0;
3460 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3461 byte_count = params + 1 /* pad */ ;
3462 pSMB->TotalParameterCount = cpu_to_le16(params);
3463 pSMB->ParameterCount = pSMB->TotalParameterCount;
3464 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3465 pSMB->Reserved4 = 0;
3466 pSMB->hdr.smb_buf_length += byte_count;
3467 pSMB->ByteCount = cpu_to_le16(byte_count);
3469 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3470 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3472 cFYI(1, ("Send error in QPathInfo = %d", rc));
3473 } else { /* decode response */
3474 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3476 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3477 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3478 "Unix Extensions can be disabled on mount "
3479 "by specifying the nosfu mount option."));
3480 rc = -EIO; /* bad smb */
3482 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3483 memcpy((char *) pFindData,
3484 (char *) &pSMBr->hdr.Protocol +
3486 sizeof(FILE_UNIX_BASIC_INFO));
3489 cifs_buf_release(pSMB);
3491 goto UnixQPathInfoRetry;
3496 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3498 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3499 const char *searchName,
3500 const struct nls_table *nls_codepage,
3502 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3504 /* level 257 SMB_ */
3505 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3506 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3507 T2_FFIRST_RSP_PARMS *parms;
3509 int bytes_returned = 0;
3511 __u16 params, byte_count;
3513 cFYI(1, ("In FindFirst for %s", searchName));
3516 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3521 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3523 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3524 PATH_MAX, nls_codepage, remap);
3525 /* We can not add the asterik earlier in case
3526 it got remapped to 0xF03A as if it were part of the
3527 directory name instead of a wildcard */
3529 pSMB->FileName[name_len] = dirsep;
3530 pSMB->FileName[name_len+1] = 0;
3531 pSMB->FileName[name_len+2] = '*';
3532 pSMB->FileName[name_len+3] = 0;
3533 name_len += 4; /* now the trailing null */
3534 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3535 pSMB->FileName[name_len+1] = 0;
3537 } else { /* BB add check for overrun of SMB buf BB */
3538 name_len = strnlen(searchName, PATH_MAX);
3539 /* BB fix here and in unicode clause above ie
3540 if (name_len > buffersize-header)
3541 free buffer exit; BB */
3542 strncpy(pSMB->FileName, searchName, name_len);
3543 pSMB->FileName[name_len] = dirsep;
3544 pSMB->FileName[name_len+1] = '*';
3545 pSMB->FileName[name_len+2] = 0;
3549 params = 12 + name_len /* includes null */ ;
3550 pSMB->TotalDataCount = 0; /* no EAs */
3551 pSMB->MaxParameterCount = cpu_to_le16(10);
3552 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3553 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3554 pSMB->MaxSetupCount = 0;
3558 pSMB->Reserved2 = 0;
3559 byte_count = params + 1 /* pad */ ;
3560 pSMB->TotalParameterCount = cpu_to_le16(params);
3561 pSMB->ParameterCount = pSMB->TotalParameterCount;
3562 pSMB->ParameterOffset = cpu_to_le16(
3563 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3565 pSMB->DataCount = 0;
3566 pSMB->DataOffset = 0;
3567 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3568 pSMB->Reserved3 = 0;
3569 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3570 pSMB->SearchAttributes =
3571 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3573 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3574 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3575 CIFS_SEARCH_RETURN_RESUME);
3576 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3578 /* BB what should we set StorageType to? Does it matter? BB */
3579 pSMB->SearchStorageType = 0;
3580 pSMB->hdr.smb_buf_length += byte_count;
3581 pSMB->ByteCount = cpu_to_le16(byte_count);
3583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3585 cifs_stats_inc(&tcon->num_ffirst);
3587 if (rc) {/* BB add logic to retry regular search if Unix search
3588 rejected unexpectedly by server */
3589 /* BB Add code to handle unsupported level rc */
3590 cFYI(1, ("Error in FindFirst = %d", rc));
3592 cifs_buf_release(pSMB);
3594 /* BB eventually could optimize out free and realloc of buf */
3597 goto findFirstRetry;
3598 } else { /* decode response */
3599 /* BB remember to free buffer if error BB */
3600 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3604 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3605 psrch_inf->unicode = true;
3607 psrch_inf->unicode = false;
3609 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3610 psrch_inf->smallBuf = 0;
3611 psrch_inf->srch_entries_start =
3612 (char *) &pSMBr->hdr.Protocol +
3613 le16_to_cpu(pSMBr->t2.DataOffset);
3614 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3615 le16_to_cpu(pSMBr->t2.ParameterOffset));
3617 if (parms->EndofSearch)
3618 psrch_inf->endOfSearch = true;
3620 psrch_inf->endOfSearch = false;
3622 psrch_inf->entries_in_buffer =
3623 le16_to_cpu(parms->SearchCount);
3624 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3625 psrch_inf->entries_in_buffer;
3626 lnoff = le16_to_cpu(parms->LastNameOffset);
3627 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3629 cERROR(1, ("ignoring corrupt resume name"));
3630 psrch_inf->last_entry = NULL;
3634 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3637 *pnetfid = parms->SearchHandle;
3639 cifs_buf_release(pSMB);
3646 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3647 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3649 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3650 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3651 T2_FNEXT_RSP_PARMS *parms;
3652 char *response_data;
3654 int bytes_returned, name_len;
3655 __u16 params, byte_count;
3657 cFYI(1, ("In FindNext"));
3659 if (psrch_inf->endOfSearch)
3662 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3667 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3669 pSMB->TotalDataCount = 0; /* no EAs */
3670 pSMB->MaxParameterCount = cpu_to_le16(8);
3671 pSMB->MaxDataCount =
3672 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3674 pSMB->MaxSetupCount = 0;
3678 pSMB->Reserved2 = 0;
3679 pSMB->ParameterOffset = cpu_to_le16(
3680 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3681 pSMB->DataCount = 0;
3682 pSMB->DataOffset = 0;
3683 pSMB->SetupCount = 1;
3684 pSMB->Reserved3 = 0;
3685 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3686 pSMB->SearchHandle = searchHandle; /* always kept as le */
3688 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3689 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3690 pSMB->ResumeKey = psrch_inf->resume_key;
3692 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3694 name_len = psrch_inf->resume_name_len;
3696 if (name_len < PATH_MAX) {
3697 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3698 byte_count += name_len;
3699 /* 14 byte parm len above enough for 2 byte null terminator */
3700 pSMB->ResumeFileName[name_len] = 0;
3701 pSMB->ResumeFileName[name_len+1] = 0;
3704 goto FNext2_err_exit;
3706 byte_count = params + 1 /* pad */ ;
3707 pSMB->TotalParameterCount = cpu_to_le16(params);
3708 pSMB->ParameterCount = pSMB->TotalParameterCount;
3709 pSMB->hdr.smb_buf_length += byte_count;
3710 pSMB->ByteCount = cpu_to_le16(byte_count);
3712 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3713 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3714 cifs_stats_inc(&tcon->num_fnext);
3717 psrch_inf->endOfSearch = true;
3718 cifs_buf_release(pSMB);
3719 rc = 0; /* search probably was closed at end of search*/
3721 cFYI(1, ("FindNext returned = %d", rc));
3722 } else { /* decode response */
3723 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3728 /* BB fixme add lock for file (srch_info) struct here */
3729 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3730 psrch_inf->unicode = true;
3732 psrch_inf->unicode = false;
3733 response_data = (char *) &pSMBr->hdr.Protocol +
3734 le16_to_cpu(pSMBr->t2.ParameterOffset);
3735 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3736 response_data = (char *)&pSMBr->hdr.Protocol +
3737 le16_to_cpu(pSMBr->t2.DataOffset);
3738 if (psrch_inf->smallBuf)
3739 cifs_small_buf_release(
3740 psrch_inf->ntwrk_buf_start);
3742 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3743 psrch_inf->srch_entries_start = response_data;
3744 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3745 psrch_inf->smallBuf = 0;
3746 if (parms->EndofSearch)
3747 psrch_inf->endOfSearch = true;
3749 psrch_inf->endOfSearch = false;
3750 psrch_inf->entries_in_buffer =
3751 le16_to_cpu(parms->SearchCount);
3752 psrch_inf->index_of_last_entry +=
3753 psrch_inf->entries_in_buffer;
3754 lnoff = le16_to_cpu(parms->LastNameOffset);
3755 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3757 cERROR(1, ("ignoring corrupt resume name"));
3758 psrch_inf->last_entry = NULL;
3761 psrch_inf->last_entry =
3762 psrch_inf->srch_entries_start + lnoff;
3764 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3765 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3767 /* BB fixme add unlock here */
3772 /* BB On error, should we leave previous search buf (and count and
3773 last entry fields) intact or free the previous one? */
3775 /* Note: On -EAGAIN error only caller can retry on handle based calls
3776 since file handle passed in no longer valid */
3779 cifs_buf_release(pSMB);
3784 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3785 const __u16 searchHandle)
3788 FINDCLOSE_REQ *pSMB = NULL;
3790 cFYI(1, ("In CIFSSMBFindClose"));
3791 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3793 /* no sense returning error if session restarted
3794 as file handle has been closed */
3800 pSMB->FileID = searchHandle;
3801 pSMB->ByteCount = 0;
3802 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3804 cERROR(1, ("Send error in FindClose = %d", rc));
3806 cifs_stats_inc(&tcon->num_fclose);
3808 /* Since session is dead, search handle closed on server already */
3816 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3817 const unsigned char *searchName,
3818 __u64 *inode_number,
3819 const struct nls_table *nls_codepage, int remap)
3822 TRANSACTION2_QPI_REQ *pSMB = NULL;
3823 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3824 int name_len, bytes_returned;
3825 __u16 params, byte_count;
3827 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3831 GetInodeNumberRetry:
3832 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3837 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3839 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3840 PATH_MAX, nls_codepage, remap);
3841 name_len++; /* trailing null */
3843 } else { /* BB improve the check for buffer overruns BB */
3844 name_len = strnlen(searchName, PATH_MAX);
3845 name_len++; /* trailing null */
3846 strncpy(pSMB->FileName, searchName, name_len);
3849 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3850 pSMB->TotalDataCount = 0;
3851 pSMB->MaxParameterCount = cpu_to_le16(2);
3852 /* BB find exact max data count below from sess structure BB */
3853 pSMB->MaxDataCount = cpu_to_le16(4000);
3854 pSMB->MaxSetupCount = 0;
3858 pSMB->Reserved2 = 0;
3859 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3860 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3861 pSMB->DataCount = 0;
3862 pSMB->DataOffset = 0;
3863 pSMB->SetupCount = 1;
3864 pSMB->Reserved3 = 0;
3865 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3866 byte_count = params + 1 /* pad */ ;
3867 pSMB->TotalParameterCount = cpu_to_le16(params);
3868 pSMB->ParameterCount = pSMB->TotalParameterCount;
3869 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3870 pSMB->Reserved4 = 0;
3871 pSMB->hdr.smb_buf_length += byte_count;
3872 pSMB->ByteCount = cpu_to_le16(byte_count);
3874 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3875 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3877 cFYI(1, ("error %d in QueryInternalInfo", rc));
3879 /* decode response */
3880 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3881 if (rc || (pSMBr->ByteCount < 2))
3882 /* BB also check enough total bytes returned */
3883 /* If rc should we check for EOPNOSUPP and
3884 disable the srvino flag? or in caller? */
3885 rc = -EIO; /* bad smb */
3887 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3888 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3889 struct file_internal_info *pfinfo;
3890 /* BB Do we need a cast or hash here ? */
3892 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3894 goto GetInodeNumOut;
3896 pfinfo = (struct file_internal_info *)
3897 (data_offset + (char *) &pSMBr->hdr.Protocol);
3898 *inode_number = pfinfo->UniqueId;
3902 cifs_buf_release(pSMB);
3904 goto GetInodeNumberRetry;
3908 /* computes length of UCS string converted to host codepage
3910 * @maxlen: length of the input string in UCS characters
3913 * return: size of input string in host codepage
3915 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3916 const struct nls_table *nls_codepage) {
3921 for (i = 0; (i < maxlen) && src[i]; ++i) {
3922 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3923 to, NLS_MAX_CHARSET_SIZE);
3924 hostlen += charlen > 0 ? charlen : 1;
3929 /* parses DFS refferal V3 structure
3930 * caller is responsible for freeing target_nodes
3933 * on failure - errno
3936 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3937 unsigned int *num_of_nodes,
3938 struct dfs_info3_param **target_nodes,
3939 const struct nls_table *nls_codepage, int remap,
3940 const char *searchName)
3945 struct dfs_referral_level_3 *ref;
3947 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3951 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3953 if (*num_of_nodes < 1) {
3954 cERROR(1, ("num_referrals: must be at least > 0,"
3955 "but we get num_referrals = %d\n", *num_of_nodes));
3957 goto parse_DFS_referrals_exit;
3960 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3961 if (ref->VersionNumber != cpu_to_le16(3)) {
3962 cERROR(1, ("Referrals of V%d version are not supported,"
3963 "should be V3", le16_to_cpu(ref->VersionNumber)));
3965 goto parse_DFS_referrals_exit;
3968 /* get the upper boundary of the resp buffer */
3969 data_end = (char *)(&(pSMBr->PathConsumed)) +
3970 le16_to_cpu(pSMBr->t2.DataCount);
3972 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3974 le16_to_cpu(pSMBr->DFSFlags)));
3976 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3977 *num_of_nodes, GFP_KERNEL);
3978 if (*target_nodes == NULL) {
3979 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3981 goto parse_DFS_referrals_exit;
3984 /* collect neccessary data from referrals */
3985 for (i = 0; i < *num_of_nodes; i++) {
3988 struct dfs_info3_param *node = (*target_nodes)+i;
3990 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3992 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3994 cifsConvertToUCS((__le16 *) tmp, searchName,
3995 PATH_MAX, nls_codepage, remap);
3996 node->path_consumed = hostlen_fromUCS(tmp,
3997 le16_to_cpu(pSMBr->PathConsumed)/2,
4001 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4003 node->server_type = le16_to_cpu(ref->ServerType);
4004 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4007 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4008 max_len = data_end - temp;
4009 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4010 max_len, is_unicode, nls_codepage);
4012 goto parse_DFS_referrals_exit;
4014 /* copy link target UNC */
4015 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4016 max_len = data_end - temp;
4017 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4018 max_len, is_unicode, nls_codepage);
4020 goto parse_DFS_referrals_exit;
4022 ref += le16_to_cpu(ref->Size);
4025 parse_DFS_referrals_exit:
4027 free_dfs_info_array(*target_nodes, *num_of_nodes);
4028 *target_nodes = NULL;
4035 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4036 const unsigned char *searchName,
4037 struct dfs_info3_param **target_nodes,
4038 unsigned int *num_of_nodes,
4039 const struct nls_table *nls_codepage, int remap)
4041 /* TRANS2_GET_DFS_REFERRAL */
4042 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4043 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4047 __u16 params, byte_count;
4049 *target_nodes = NULL;
4051 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4055 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4060 /* server pointer checked in called function,
4061 but should never be null here anyway */
4062 pSMB->hdr.Mid = GetNextMid(ses->server);
4063 pSMB->hdr.Tid = ses->ipc_tid;
4064 pSMB->hdr.Uid = ses->Suid;
4065 if (ses->capabilities & CAP_STATUS32)
4066 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4067 if (ses->capabilities & CAP_DFS)
4068 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4070 if (ses->capabilities & CAP_UNICODE) {
4071 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4073 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4074 searchName, PATH_MAX, nls_codepage, remap);
4075 name_len++; /* trailing null */
4077 } else { /* BB improve the check for buffer overruns BB */
4078 name_len = strnlen(searchName, PATH_MAX);
4079 name_len++; /* trailing null */
4080 strncpy(pSMB->RequestFileName, searchName, name_len);
4084 if (ses->server->secMode &
4085 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4086 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4089 pSMB->hdr.Uid = ses->Suid;
4091 params = 2 /* level */ + name_len /*includes null */ ;
4092 pSMB->TotalDataCount = 0;
4093 pSMB->DataCount = 0;
4094 pSMB->DataOffset = 0;
4095 pSMB->MaxParameterCount = 0;
4096 /* BB find exact max SMB PDU from sess structure BB */
4097 pSMB->MaxDataCount = cpu_to_le16(4000);
4098 pSMB->MaxSetupCount = 0;
4102 pSMB->Reserved2 = 0;
4103 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4104 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4105 pSMB->SetupCount = 1;
4106 pSMB->Reserved3 = 0;
4107 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4108 byte_count = params + 3 /* pad */ ;
4109 pSMB->ParameterCount = cpu_to_le16(params);
4110 pSMB->TotalParameterCount = pSMB->ParameterCount;
4111 pSMB->MaxReferralLevel = cpu_to_le16(3);
4112 pSMB->hdr.smb_buf_length += byte_count;
4113 pSMB->ByteCount = cpu_to_le16(byte_count);
4115 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4116 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4118 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4121 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4123 /* BB Also check if enough total bytes returned? */
4124 if (rc || (pSMBr->ByteCount < 17)) {
4125 rc = -EIO; /* bad smb */
4129 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4131 le16_to_cpu(pSMBr->t2.DataOffset)));
4133 /* parse returned result into more usable form */
4134 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4135 target_nodes, nls_codepage, remap,
4139 cifs_buf_release(pSMB);
4147 /* Query File System Info such as free space to old servers such as Win 9x */
4149 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4151 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4152 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4153 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4154 FILE_SYSTEM_ALLOC_INFO *response_data;
4156 int bytes_returned = 0;
4157 __u16 params, byte_count;
4159 cFYI(1, ("OldQFSInfo"));
4161 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4166 params = 2; /* level */
4167 pSMB->TotalDataCount = 0;
4168 pSMB->MaxParameterCount = cpu_to_le16(2);
4169 pSMB->MaxDataCount = cpu_to_le16(1000);
4170 pSMB->MaxSetupCount = 0;
4174 pSMB->Reserved2 = 0;
4175 byte_count = params + 1 /* pad */ ;
4176 pSMB->TotalParameterCount = cpu_to_le16(params);
4177 pSMB->ParameterCount = pSMB->TotalParameterCount;
4178 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4179 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4180 pSMB->DataCount = 0;
4181 pSMB->DataOffset = 0;
4182 pSMB->SetupCount = 1;
4183 pSMB->Reserved3 = 0;
4184 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4185 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4186 pSMB->hdr.smb_buf_length += byte_count;
4187 pSMB->ByteCount = cpu_to_le16(byte_count);
4189 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4190 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4192 cFYI(1, ("Send error in QFSInfo = %d", rc));
4193 } else { /* decode response */
4194 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4196 if (rc || (pSMBr->ByteCount < 18))
4197 rc = -EIO; /* bad smb */
4199 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4200 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4201 pSMBr->ByteCount, data_offset));
4203 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4204 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4206 le16_to_cpu(response_data->BytesPerSector) *
4207 le32_to_cpu(response_data->
4208 SectorsPerAllocationUnit);
4210 le32_to_cpu(response_data->TotalAllocationUnits);
4211 FSData->f_bfree = FSData->f_bavail =
4212 le32_to_cpu(response_data->FreeAllocationUnits);
4214 ("Blocks: %lld Free: %lld Block size %ld",
4215 (unsigned long long)FSData->f_blocks,
4216 (unsigned long long)FSData->f_bfree,
4220 cifs_buf_release(pSMB);
4223 goto oldQFSInfoRetry;
4229 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4231 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4232 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4233 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4234 FILE_SYSTEM_INFO *response_data;
4236 int bytes_returned = 0;
4237 __u16 params, byte_count;
4239 cFYI(1, ("In QFSInfo"));
4241 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4246 params = 2; /* level */
4247 pSMB->TotalDataCount = 0;
4248 pSMB->MaxParameterCount = cpu_to_le16(2);
4249 pSMB->MaxDataCount = cpu_to_le16(1000);
4250 pSMB->MaxSetupCount = 0;
4254 pSMB->Reserved2 = 0;
4255 byte_count = params + 1 /* pad */ ;
4256 pSMB->TotalParameterCount = cpu_to_le16(params);
4257 pSMB->ParameterCount = pSMB->TotalParameterCount;
4258 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4259 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4260 pSMB->DataCount = 0;
4261 pSMB->DataOffset = 0;
4262 pSMB->SetupCount = 1;
4263 pSMB->Reserved3 = 0;
4264 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4265 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4266 pSMB->hdr.smb_buf_length += byte_count;
4267 pSMB->ByteCount = cpu_to_le16(byte_count);
4269 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4270 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4272 cFYI(1, ("Send error in QFSInfo = %d", rc));
4273 } else { /* decode response */
4274 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4276 if (rc || (pSMBr->ByteCount < 24))
4277 rc = -EIO; /* bad smb */
4279 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4283 *) (((char *) &pSMBr->hdr.Protocol) +
4286 le32_to_cpu(response_data->BytesPerSector) *
4287 le32_to_cpu(response_data->
4288 SectorsPerAllocationUnit);
4290 le64_to_cpu(response_data->TotalAllocationUnits);
4291 FSData->f_bfree = FSData->f_bavail =
4292 le64_to_cpu(response_data->FreeAllocationUnits);
4294 ("Blocks: %lld Free: %lld Block size %ld",
4295 (unsigned long long)FSData->f_blocks,
4296 (unsigned long long)FSData->f_bfree,
4300 cifs_buf_release(pSMB);
4309 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4311 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4312 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4313 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4314 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4316 int bytes_returned = 0;
4317 __u16 params, byte_count;
4319 cFYI(1, ("In QFSAttributeInfo"));
4321 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4326 params = 2; /* level */
4327 pSMB->TotalDataCount = 0;
4328 pSMB->MaxParameterCount = cpu_to_le16(2);
4329 /* BB find exact max SMB PDU from sess structure BB */
4330 pSMB->MaxDataCount = cpu_to_le16(1000);
4331 pSMB->MaxSetupCount = 0;
4335 pSMB->Reserved2 = 0;
4336 byte_count = params + 1 /* pad */ ;
4337 pSMB->TotalParameterCount = cpu_to_le16(params);
4338 pSMB->ParameterCount = pSMB->TotalParameterCount;
4339 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4340 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4341 pSMB->DataCount = 0;
4342 pSMB->DataOffset = 0;
4343 pSMB->SetupCount = 1;
4344 pSMB->Reserved3 = 0;
4345 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4346 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4347 pSMB->hdr.smb_buf_length += byte_count;
4348 pSMB->ByteCount = cpu_to_le16(byte_count);
4350 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4351 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4353 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4354 } else { /* decode response */
4355 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4357 if (rc || (pSMBr->ByteCount < 13)) {
4358 /* BB also check if enough bytes returned */
4359 rc = -EIO; /* bad smb */
4361 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4363 (FILE_SYSTEM_ATTRIBUTE_INFO
4364 *) (((char *) &pSMBr->hdr.Protocol) +
4366 memcpy(&tcon->fsAttrInfo, response_data,
4367 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4370 cifs_buf_release(pSMB);
4373 goto QFSAttributeRetry;
4379 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4381 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4382 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4383 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4384 FILE_SYSTEM_DEVICE_INFO *response_data;
4386 int bytes_returned = 0;
4387 __u16 params, byte_count;
4389 cFYI(1, ("In QFSDeviceInfo"));
4391 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4396 params = 2; /* level */
4397 pSMB->TotalDataCount = 0;
4398 pSMB->MaxParameterCount = cpu_to_le16(2);
4399 /* BB find exact max SMB PDU from sess structure BB */
4400 pSMB->MaxDataCount = cpu_to_le16(1000);
4401 pSMB->MaxSetupCount = 0;
4405 pSMB->Reserved2 = 0;
4406 byte_count = params + 1 /* pad */ ;
4407 pSMB->TotalParameterCount = cpu_to_le16(params);
4408 pSMB->ParameterCount = pSMB->TotalParameterCount;
4409 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4410 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4412 pSMB->DataCount = 0;
4413 pSMB->DataOffset = 0;
4414 pSMB->SetupCount = 1;
4415 pSMB->Reserved3 = 0;
4416 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4417 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4418 pSMB->hdr.smb_buf_length += byte_count;
4419 pSMB->ByteCount = cpu_to_le16(byte_count);
4421 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4422 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4424 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4425 } else { /* decode response */
4426 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4428 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4429 rc = -EIO; /* bad smb */
4431 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4433 (FILE_SYSTEM_DEVICE_INFO *)
4434 (((char *) &pSMBr->hdr.Protocol) +
4436 memcpy(&tcon->fsDevInfo, response_data,
4437 sizeof(FILE_SYSTEM_DEVICE_INFO));
4440 cifs_buf_release(pSMB);
4443 goto QFSDeviceRetry;
4449 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4451 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4452 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4453 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4454 FILE_SYSTEM_UNIX_INFO *response_data;
4456 int bytes_returned = 0;
4457 __u16 params, byte_count;
4459 cFYI(1, ("In QFSUnixInfo"));
4461 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4466 params = 2; /* level */
4467 pSMB->TotalDataCount = 0;
4468 pSMB->DataCount = 0;
4469 pSMB->DataOffset = 0;
4470 pSMB->MaxParameterCount = cpu_to_le16(2);
4471 /* BB find exact max SMB PDU from sess structure BB */
4472 pSMB->MaxDataCount = cpu_to_le16(100);
4473 pSMB->MaxSetupCount = 0;
4477 pSMB->Reserved2 = 0;
4478 byte_count = params + 1 /* pad */ ;
4479 pSMB->ParameterCount = cpu_to_le16(params);
4480 pSMB->TotalParameterCount = pSMB->ParameterCount;
4481 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4482 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4483 pSMB->SetupCount = 1;
4484 pSMB->Reserved3 = 0;
4485 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4486 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4487 pSMB->hdr.smb_buf_length += byte_count;
4488 pSMB->ByteCount = cpu_to_le16(byte_count);
4490 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4491 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4493 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4494 } else { /* decode response */
4495 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4497 if (rc || (pSMBr->ByteCount < 13)) {
4498 rc = -EIO; /* bad smb */
4500 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4502 (FILE_SYSTEM_UNIX_INFO
4503 *) (((char *) &pSMBr->hdr.Protocol) +
4505 memcpy(&tcon->fsUnixInfo, response_data,
4506 sizeof(FILE_SYSTEM_UNIX_INFO));
4509 cifs_buf_release(pSMB);
4519 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4521 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4522 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4523 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4525 int bytes_returned = 0;
4526 __u16 params, param_offset, offset, byte_count;
4528 cFYI(1, ("In SETFSUnixInfo"));
4530 /* BB switch to small buf init to save memory */
4531 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4536 params = 4; /* 2 bytes zero followed by info level. */
4537 pSMB->MaxSetupCount = 0;
4541 pSMB->Reserved2 = 0;
4542 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4544 offset = param_offset + params;
4546 pSMB->MaxParameterCount = cpu_to_le16(4);
4547 /* BB find exact max SMB PDU from sess structure BB */
4548 pSMB->MaxDataCount = cpu_to_le16(100);
4549 pSMB->SetupCount = 1;
4550 pSMB->Reserved3 = 0;
4551 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4552 byte_count = 1 /* pad */ + params + 12;
4554 pSMB->DataCount = cpu_to_le16(12);
4555 pSMB->ParameterCount = cpu_to_le16(params);
4556 pSMB->TotalDataCount = pSMB->DataCount;
4557 pSMB->TotalParameterCount = pSMB->ParameterCount;
4558 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4559 pSMB->DataOffset = cpu_to_le16(offset);
4563 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4566 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4567 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4568 pSMB->ClientUnixCap = cpu_to_le64(cap);
4570 pSMB->hdr.smb_buf_length += byte_count;
4571 pSMB->ByteCount = cpu_to_le16(byte_count);
4573 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4574 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4576 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4577 } else { /* decode response */
4578 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4580 rc = -EIO; /* bad smb */
4582 cifs_buf_release(pSMB);
4585 goto SETFSUnixRetry;
4593 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4594 struct kstatfs *FSData)
4596 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4597 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4598 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4599 FILE_SYSTEM_POSIX_INFO *response_data;
4601 int bytes_returned = 0;
4602 __u16 params, byte_count;
4604 cFYI(1, ("In QFSPosixInfo"));
4606 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4611 params = 2; /* level */
4612 pSMB->TotalDataCount = 0;
4613 pSMB->DataCount = 0;
4614 pSMB->DataOffset = 0;
4615 pSMB->MaxParameterCount = cpu_to_le16(2);
4616 /* BB find exact max SMB PDU from sess structure BB */
4617 pSMB->MaxDataCount = cpu_to_le16(100);
4618 pSMB->MaxSetupCount = 0;
4622 pSMB->Reserved2 = 0;
4623 byte_count = params + 1 /* pad */ ;
4624 pSMB->ParameterCount = cpu_to_le16(params);
4625 pSMB->TotalParameterCount = pSMB->ParameterCount;
4626 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4627 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4628 pSMB->SetupCount = 1;
4629 pSMB->Reserved3 = 0;
4630 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4631 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4632 pSMB->hdr.smb_buf_length += byte_count;
4633 pSMB->ByteCount = cpu_to_le16(byte_count);
4635 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4636 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4638 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4639 } else { /* decode response */
4640 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4642 if (rc || (pSMBr->ByteCount < 13)) {
4643 rc = -EIO; /* bad smb */
4645 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4647 (FILE_SYSTEM_POSIX_INFO
4648 *) (((char *) &pSMBr->hdr.Protocol) +
4651 le32_to_cpu(response_data->BlockSize);
4653 le64_to_cpu(response_data->TotalBlocks);
4655 le64_to_cpu(response_data->BlocksAvail);
4656 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4657 FSData->f_bavail = FSData->f_bfree;
4660 le64_to_cpu(response_data->UserBlocksAvail);
4662 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4664 le64_to_cpu(response_data->TotalFileNodes);
4665 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4667 le64_to_cpu(response_data->FreeFileNodes);
4670 cifs_buf_release(pSMB);
4679 /* We can not use write of zero bytes trick to
4680 set file size due to need for large file support. Also note that
4681 this SetPathInfo is preferred to SetFileInfo based method in next
4682 routine which is only needed to work around a sharing violation bug
4683 in Samba which this routine can run into */
4686 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4687 __u64 size, bool SetAllocation,
4688 const struct nls_table *nls_codepage, int remap)
4690 struct smb_com_transaction2_spi_req *pSMB = NULL;
4691 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4692 struct file_end_of_file_info *parm_data;
4695 int bytes_returned = 0;
4696 __u16 params, byte_count, data_count, param_offset, offset;
4698 cFYI(1, ("In SetEOF"));
4700 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4705 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4707 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4708 PATH_MAX, nls_codepage, remap);
4709 name_len++; /* trailing null */
4711 } else { /* BB improve the check for buffer overruns BB */
4712 name_len = strnlen(fileName, PATH_MAX);
4713 name_len++; /* trailing null */
4714 strncpy(pSMB->FileName, fileName, name_len);
4716 params = 6 + name_len;
4717 data_count = sizeof(struct file_end_of_file_info);
4718 pSMB->MaxParameterCount = cpu_to_le16(2);
4719 pSMB->MaxDataCount = cpu_to_le16(4100);
4720 pSMB->MaxSetupCount = 0;
4724 pSMB->Reserved2 = 0;
4725 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4726 InformationLevel) - 4;
4727 offset = param_offset + params;
4728 if (SetAllocation) {
4729 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4730 pSMB->InformationLevel =
4731 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4733 pSMB->InformationLevel =
4734 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4735 } else /* Set File Size */ {
4736 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4737 pSMB->InformationLevel =
4738 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4740 pSMB->InformationLevel =
4741 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4745 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4747 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4748 pSMB->DataOffset = cpu_to_le16(offset);
4749 pSMB->SetupCount = 1;
4750 pSMB->Reserved3 = 0;
4751 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4752 byte_count = 3 /* pad */ + params + data_count;
4753 pSMB->DataCount = cpu_to_le16(data_count);
4754 pSMB->TotalDataCount = pSMB->DataCount;
4755 pSMB->ParameterCount = cpu_to_le16(params);
4756 pSMB->TotalParameterCount = pSMB->ParameterCount;
4757 pSMB->Reserved4 = 0;
4758 pSMB->hdr.smb_buf_length += byte_count;
4759 parm_data->FileSize = cpu_to_le64(size);
4760 pSMB->ByteCount = cpu_to_le16(byte_count);
4761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4764 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4766 cifs_buf_release(pSMB);
4775 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4776 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4778 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4780 struct file_end_of_file_info *parm_data;
4782 __u16 params, param_offset, offset, byte_count, count;
4784 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4786 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4791 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4792 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4795 pSMB->MaxSetupCount = 0;
4799 pSMB->Reserved2 = 0;
4800 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4801 offset = param_offset + params;
4803 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4805 count = sizeof(struct file_end_of_file_info);
4806 pSMB->MaxParameterCount = cpu_to_le16(2);
4807 /* BB find exact max SMB PDU from sess structure BB */
4808 pSMB->MaxDataCount = cpu_to_le16(1000);
4809 pSMB->SetupCount = 1;
4810 pSMB->Reserved3 = 0;
4811 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4812 byte_count = 3 /* pad */ + params + count;
4813 pSMB->DataCount = cpu_to_le16(count);
4814 pSMB->ParameterCount = cpu_to_le16(params);
4815 pSMB->TotalDataCount = pSMB->DataCount;
4816 pSMB->TotalParameterCount = pSMB->ParameterCount;
4817 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4819 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4821 pSMB->DataOffset = cpu_to_le16(offset);
4822 parm_data->FileSize = cpu_to_le64(size);
4824 if (SetAllocation) {
4825 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4826 pSMB->InformationLevel =
4827 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4829 pSMB->InformationLevel =
4830 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4831 } else /* Set File Size */ {
4832 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4833 pSMB->InformationLevel =
4834 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4836 pSMB->InformationLevel =
4837 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4839 pSMB->Reserved4 = 0;
4840 pSMB->hdr.smb_buf_length += byte_count;
4841 pSMB->ByteCount = cpu_to_le16(byte_count);
4842 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4845 ("Send error in SetFileInfo (SetFileSize) = %d",
4849 /* Note: On -EAGAIN error only caller can retry on handle based calls
4850 since file handle passed in no longer valid */
4855 /* Some legacy servers such as NT4 require that the file times be set on
4856 an open handle, rather than by pathname - this is awkward due to
4857 potential access conflicts on the open, but it is unavoidable for these
4858 old servers since the only other choice is to go from 100 nanosecond DCE
4859 time and resort to the original setpathinfo level which takes the ancient
4860 DOS time format with 2 second granularity */
4862 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4863 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4865 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4868 __u16 params, param_offset, offset, byte_count, count;
4870 cFYI(1, ("Set Times (via SetFileInfo)"));
4871 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4876 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4877 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4880 pSMB->MaxSetupCount = 0;
4884 pSMB->Reserved2 = 0;
4885 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4886 offset = param_offset + params;
4888 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4890 count = sizeof(FILE_BASIC_INFO);
4891 pSMB->MaxParameterCount = cpu_to_le16(2);
4892 /* BB find max SMB PDU from sess */
4893 pSMB->MaxDataCount = cpu_to_le16(1000);
4894 pSMB->SetupCount = 1;
4895 pSMB->Reserved3 = 0;
4896 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4897 byte_count = 3 /* pad */ + params + count;
4898 pSMB->DataCount = cpu_to_le16(count);
4899 pSMB->ParameterCount = cpu_to_le16(params);
4900 pSMB->TotalDataCount = pSMB->DataCount;
4901 pSMB->TotalParameterCount = pSMB->ParameterCount;
4902 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4903 pSMB->DataOffset = cpu_to_le16(offset);
4905 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4906 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4908 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4909 pSMB->Reserved4 = 0;
4910 pSMB->hdr.smb_buf_length += byte_count;
4911 pSMB->ByteCount = cpu_to_le16(byte_count);
4912 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4913 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4915 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4917 /* Note: On -EAGAIN error only caller can retry on handle based calls
4918 since file handle passed in no longer valid */
4924 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4925 bool delete_file, __u16 fid, __u32 pid_of_opener)
4927 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4930 __u16 params, param_offset, offset, byte_count, count;
4932 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4933 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4938 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4939 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4942 pSMB->MaxSetupCount = 0;
4946 pSMB->Reserved2 = 0;
4947 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4948 offset = param_offset + params;
4950 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4953 pSMB->MaxParameterCount = cpu_to_le16(2);
4954 /* BB find max SMB PDU from sess */
4955 pSMB->MaxDataCount = cpu_to_le16(1000);
4956 pSMB->SetupCount = 1;
4957 pSMB->Reserved3 = 0;
4958 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4959 byte_count = 3 /* pad */ + params + count;
4960 pSMB->DataCount = cpu_to_le16(count);
4961 pSMB->ParameterCount = cpu_to_le16(params);
4962 pSMB->TotalDataCount = pSMB->DataCount;
4963 pSMB->TotalParameterCount = pSMB->ParameterCount;
4964 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4965 pSMB->DataOffset = cpu_to_le16(offset);
4967 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4968 pSMB->Reserved4 = 0;
4969 pSMB->hdr.smb_buf_length += byte_count;
4970 pSMB->ByteCount = cpu_to_le16(byte_count);
4971 *data_offset = delete_file ? 1 : 0;
4972 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4974 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4980 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4981 const char *fileName, const FILE_BASIC_INFO *data,
4982 const struct nls_table *nls_codepage, int remap)
4984 TRANSACTION2_SPI_REQ *pSMB = NULL;
4985 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4988 int bytes_returned = 0;
4990 __u16 params, param_offset, offset, byte_count, count;
4992 cFYI(1, ("In SetTimes"));
4995 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5000 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5002 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5003 PATH_MAX, nls_codepage, remap);
5004 name_len++; /* trailing null */
5006 } else { /* BB improve the check for buffer overruns BB */
5007 name_len = strnlen(fileName, PATH_MAX);
5008 name_len++; /* trailing null */
5009 strncpy(pSMB->FileName, fileName, name_len);
5012 params = 6 + name_len;
5013 count = sizeof(FILE_BASIC_INFO);
5014 pSMB->MaxParameterCount = cpu_to_le16(2);
5015 /* BB find max SMB PDU from sess structure BB */
5016 pSMB->MaxDataCount = cpu_to_le16(1000);
5017 pSMB->MaxSetupCount = 0;
5021 pSMB->Reserved2 = 0;
5022 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5023 InformationLevel) - 4;
5024 offset = param_offset + params;
5025 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5026 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5027 pSMB->DataOffset = cpu_to_le16(offset);
5028 pSMB->SetupCount = 1;
5029 pSMB->Reserved3 = 0;
5030 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5031 byte_count = 3 /* pad */ + params + count;
5033 pSMB->DataCount = cpu_to_le16(count);
5034 pSMB->ParameterCount = cpu_to_le16(params);
5035 pSMB->TotalDataCount = pSMB->DataCount;
5036 pSMB->TotalParameterCount = pSMB->ParameterCount;
5037 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5038 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5040 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5041 pSMB->Reserved4 = 0;
5042 pSMB->hdr.smb_buf_length += byte_count;
5043 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5044 pSMB->ByteCount = cpu_to_le16(byte_count);
5045 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5046 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5048 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5050 cifs_buf_release(pSMB);
5058 /* Can not be used to set time stamps yet (due to old DOS time format) */
5059 /* Can be used to set attributes */
5060 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5061 handling it anyway and NT4 was what we thought it would be needed for
5062 Do not delete it until we prove whether needed for Win9x though */
5064 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5065 __u16 dos_attrs, const struct nls_table *nls_codepage)
5067 SETATTR_REQ *pSMB = NULL;
5068 SETATTR_RSP *pSMBr = NULL;
5073 cFYI(1, ("In SetAttrLegacy"));
5076 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5081 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5083 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5084 PATH_MAX, nls_codepage);
5085 name_len++; /* trailing null */
5087 } else { /* BB improve the check for buffer overruns BB */
5088 name_len = strnlen(fileName, PATH_MAX);
5089 name_len++; /* trailing null */
5090 strncpy(pSMB->fileName, fileName, name_len);
5092 pSMB->attr = cpu_to_le16(dos_attrs);
5093 pSMB->BufferFormat = 0x04;
5094 pSMB->hdr.smb_buf_length += name_len + 1;
5095 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5096 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5097 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5099 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5101 cifs_buf_release(pSMB);
5104 goto SetAttrLgcyRetry;
5108 #endif /* temporarily unneeded SetAttr legacy function */
5111 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5112 const struct cifs_unix_set_info_args *args,
5113 const struct nls_table *nls_codepage, int remap)
5115 TRANSACTION2_SPI_REQ *pSMB = NULL;
5116 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5119 int bytes_returned = 0;
5120 FILE_UNIX_BASIC_INFO *data_offset;
5121 __u16 params, param_offset, offset, count, byte_count;
5122 __u64 mode = args->mode;
5124 cFYI(1, ("In SetUID/GID/Mode"));
5126 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5131 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5133 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5134 PATH_MAX, nls_codepage, remap);
5135 name_len++; /* trailing null */
5137 } else { /* BB improve the check for buffer overruns BB */
5138 name_len = strnlen(fileName, PATH_MAX);
5139 name_len++; /* trailing null */
5140 strncpy(pSMB->FileName, fileName, name_len);
5143 params = 6 + name_len;
5144 count = sizeof(FILE_UNIX_BASIC_INFO);
5145 pSMB->MaxParameterCount = cpu_to_le16(2);
5146 /* BB find max SMB PDU from sess structure BB */
5147 pSMB->MaxDataCount = cpu_to_le16(1000);
5148 pSMB->MaxSetupCount = 0;
5152 pSMB->Reserved2 = 0;
5153 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5154 InformationLevel) - 4;
5155 offset = param_offset + params;
5157 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5159 memset(data_offset, 0, count);
5160 pSMB->DataOffset = cpu_to_le16(offset);
5161 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5162 pSMB->SetupCount = 1;
5163 pSMB->Reserved3 = 0;
5164 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5165 byte_count = 3 /* pad */ + params + count;
5166 pSMB->ParameterCount = cpu_to_le16(params);
5167 pSMB->DataCount = cpu_to_le16(count);
5168 pSMB->TotalParameterCount = pSMB->ParameterCount;
5169 pSMB->TotalDataCount = pSMB->DataCount;
5170 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5171 pSMB->Reserved4 = 0;
5172 pSMB->hdr.smb_buf_length += byte_count;
5173 /* Samba server ignores set of file size to zero due to bugs in some
5174 older clients, but we should be precise - we use SetFileSize to
5175 set file size and do not want to truncate file size to zero
5176 accidently as happened on one Samba server beta by putting
5177 zero instead of -1 here */
5178 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5179 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5180 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5181 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5182 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5183 data_offset->Uid = cpu_to_le64(args->uid);
5184 data_offset->Gid = cpu_to_le64(args->gid);
5185 /* better to leave device as zero when it is */
5186 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5187 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5188 data_offset->Permissions = cpu_to_le64(mode);
5191 data_offset->Type = cpu_to_le32(UNIX_FILE);
5192 else if (S_ISDIR(mode))
5193 data_offset->Type = cpu_to_le32(UNIX_DIR);
5194 else if (S_ISLNK(mode))
5195 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5196 else if (S_ISCHR(mode))
5197 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5198 else if (S_ISBLK(mode))
5199 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5200 else if (S_ISFIFO(mode))
5201 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5202 else if (S_ISSOCK(mode))
5203 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5206 pSMB->ByteCount = cpu_to_le16(byte_count);
5207 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5208 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5210 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5212 cifs_buf_release(pSMB);
5218 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5219 const int notify_subdirs, const __u16 netfid,
5220 __u32 filter, struct file *pfile, int multishot,
5221 const struct nls_table *nls_codepage)
5224 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5225 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5226 struct dir_notify_req *dnotify_req;
5229 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5230 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5235 pSMB->TotalParameterCount = 0 ;
5236 pSMB->TotalDataCount = 0;
5237 pSMB->MaxParameterCount = cpu_to_le32(2);
5238 /* BB find exact data count max from sess structure BB */
5239 pSMB->MaxDataCount = 0; /* same in little endian or be */
5240 /* BB VERIFY verify which is correct for above BB */
5241 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5242 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5244 pSMB->MaxSetupCount = 4;
5246 pSMB->ParameterOffset = 0;
5247 pSMB->DataCount = 0;
5248 pSMB->DataOffset = 0;
5249 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5250 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5251 pSMB->ParameterCount = pSMB->TotalParameterCount;
5253 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5254 pSMB->Reserved2 = 0;
5255 pSMB->CompletionFilter = cpu_to_le32(filter);
5256 pSMB->Fid = netfid; /* file handle always le */
5257 pSMB->ByteCount = 0;
5259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5260 (struct smb_hdr *)pSMBr, &bytes_returned,
5263 cFYI(1, ("Error in Notify = %d", rc));
5265 /* Add file to outstanding requests */
5266 /* BB change to kmem cache alloc */
5267 dnotify_req = kmalloc(
5268 sizeof(struct dir_notify_req),
5271 dnotify_req->Pid = pSMB->hdr.Pid;
5272 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5273 dnotify_req->Mid = pSMB->hdr.Mid;
5274 dnotify_req->Tid = pSMB->hdr.Tid;
5275 dnotify_req->Uid = pSMB->hdr.Uid;
5276 dnotify_req->netfid = netfid;
5277 dnotify_req->pfile = pfile;
5278 dnotify_req->filter = filter;
5279 dnotify_req->multishot = multishot;
5280 spin_lock(&GlobalMid_Lock);
5281 list_add_tail(&dnotify_req->lhead,
5282 &GlobalDnotifyReqList);
5283 spin_unlock(&GlobalMid_Lock);
5287 cifs_buf_release(pSMB);
5290 #ifdef CONFIG_CIFS_XATTR
5292 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5293 const unsigned char *searchName,
5294 char *EAData, size_t buf_size,
5295 const struct nls_table *nls_codepage, int remap)
5297 /* BB assumes one setup word */
5298 TRANSACTION2_QPI_REQ *pSMB = NULL;
5299 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5303 struct fea *temp_fea;
5305 __u16 params, byte_count;
5307 cFYI(1, ("In Query All EAs path %s", searchName));
5309 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5314 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5316 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5317 PATH_MAX, nls_codepage, remap);
5318 name_len++; /* trailing null */
5320 } else { /* BB improve the check for buffer overruns BB */
5321 name_len = strnlen(searchName, PATH_MAX);
5322 name_len++; /* trailing null */
5323 strncpy(pSMB->FileName, searchName, name_len);
5326 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5327 pSMB->TotalDataCount = 0;
5328 pSMB->MaxParameterCount = cpu_to_le16(2);
5329 /* BB find exact max SMB PDU from sess structure BB */
5330 pSMB->MaxDataCount = cpu_to_le16(4000);
5331 pSMB->MaxSetupCount = 0;
5335 pSMB->Reserved2 = 0;
5336 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5337 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5338 pSMB->DataCount = 0;
5339 pSMB->DataOffset = 0;
5340 pSMB->SetupCount = 1;
5341 pSMB->Reserved3 = 0;
5342 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5343 byte_count = params + 1 /* pad */ ;
5344 pSMB->TotalParameterCount = cpu_to_le16(params);
5345 pSMB->ParameterCount = pSMB->TotalParameterCount;
5346 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5347 pSMB->Reserved4 = 0;
5348 pSMB->hdr.smb_buf_length += byte_count;
5349 pSMB->ByteCount = cpu_to_le16(byte_count);
5351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5352 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5354 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5355 } else { /* decode response */
5356 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5358 /* BB also check enough total bytes returned */
5359 /* BB we need to improve the validity checking
5360 of these trans2 responses */
5361 if (rc || (pSMBr->ByteCount < 4))
5362 rc = -EIO; /* bad smb */
5363 /* else if (pFindData){
5364 memcpy((char *) pFindData,
5365 (char *) &pSMBr->hdr.Protocol +
5368 /* check that length of list is not more than bcc */
5369 /* check that each entry does not go beyond length
5371 /* check that each element of each entry does not
5372 go beyond end of list */
5373 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5374 struct fealist *ea_response_data;
5376 /* validate_trans2_offsets() */
5377 /* BB check if start of smb + data_offset > &bcc+ bcc */
5378 ea_response_data = (struct fealist *)
5379 (((char *) &pSMBr->hdr.Protocol) +
5381 name_len = le32_to_cpu(ea_response_data->list_len);
5382 cFYI(1, ("ea length %d", name_len));
5383 if (name_len <= 8) {
5384 /* returned EA size zeroed at top of function */
5385 cFYI(1, ("empty EA list returned from server"));
5387 /* account for ea list len */
5389 temp_fea = ea_response_data->list;
5390 temp_ptr = (char *)temp_fea;
5391 while (name_len > 0) {
5395 rc += temp_fea->name_len;
5396 /* account for prefix user. and trailing null */
5398 if (rc < (int)buf_size) {
5399 memcpy(EAData, "user.", 5);
5401 memcpy(EAData, temp_ptr,
5402 temp_fea->name_len);
5403 EAData += temp_fea->name_len;
5404 /* null terminate name */
5406 EAData = EAData + 1;
5407 } else if (buf_size == 0) {
5408 /* skip copy - calc size only */
5410 /* stop before overrun buffer */
5414 name_len -= temp_fea->name_len;
5415 temp_ptr += temp_fea->name_len;
5416 /* account for trailing null */
5420 le16_to_cpu(temp_fea->value_len);
5421 name_len -= value_len;
5422 temp_ptr += value_len;
5423 /* BB check that temp_ptr is still
5426 /* no trailing null to account for
5428 /* go on to next EA */
5429 temp_fea = (struct fea *)temp_ptr;
5434 cifs_buf_release(pSMB);
5441 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5442 const unsigned char *searchName, const unsigned char *ea_name,
5443 unsigned char *ea_value, size_t buf_size,
5444 const struct nls_table *nls_codepage, int remap)
5446 TRANSACTION2_QPI_REQ *pSMB = NULL;
5447 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5451 struct fea *temp_fea;
5453 __u16 params, byte_count;
5455 cFYI(1, ("In Query EA path %s", searchName));
5457 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5462 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5464 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5465 PATH_MAX, nls_codepage, remap);
5466 name_len++; /* trailing null */
5468 } else { /* BB improve the check for buffer overruns BB */
5469 name_len = strnlen(searchName, PATH_MAX);
5470 name_len++; /* trailing null */
5471 strncpy(pSMB->FileName, searchName, name_len);
5474 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5475 pSMB->TotalDataCount = 0;
5476 pSMB->MaxParameterCount = cpu_to_le16(2);
5477 /* BB find exact max SMB PDU from sess structure BB */
5478 pSMB->MaxDataCount = cpu_to_le16(4000);
5479 pSMB->MaxSetupCount = 0;
5483 pSMB->Reserved2 = 0;
5484 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5485 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5486 pSMB->DataCount = 0;
5487 pSMB->DataOffset = 0;
5488 pSMB->SetupCount = 1;
5489 pSMB->Reserved3 = 0;
5490 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5491 byte_count = params + 1 /* pad */ ;
5492 pSMB->TotalParameterCount = cpu_to_le16(params);
5493 pSMB->ParameterCount = pSMB->TotalParameterCount;
5494 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5495 pSMB->Reserved4 = 0;
5496 pSMB->hdr.smb_buf_length += byte_count;
5497 pSMB->ByteCount = cpu_to_le16(byte_count);
5499 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5502 cFYI(1, ("Send error in Query EA = %d", rc));
5503 } else { /* decode response */
5504 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5506 /* BB also check enough total bytes returned */
5507 /* BB we need to improve the validity checking
5508 of these trans2 responses */
5509 if (rc || (pSMBr->ByteCount < 4))
5510 rc = -EIO; /* bad smb */
5511 /* else if (pFindData){
5512 memcpy((char *) pFindData,
5513 (char *) &pSMBr->hdr.Protocol +
5516 /* check that length of list is not more than bcc */
5517 /* check that each entry does not go beyond length
5519 /* check that each element of each entry does not
5520 go beyond end of list */
5521 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5522 struct fealist *ea_response_data;
5524 /* validate_trans2_offsets() */
5525 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5526 ea_response_data = (struct fealist *)
5527 (((char *) &pSMBr->hdr.Protocol) +
5529 name_len = le32_to_cpu(ea_response_data->list_len);
5530 cFYI(1, ("ea length %d", name_len));
5531 if (name_len <= 8) {
5532 /* returned EA size zeroed at top of function */
5533 cFYI(1, ("empty EA list returned from server"));
5535 /* account for ea list len */
5537 temp_fea = ea_response_data->list;
5538 temp_ptr = (char *)temp_fea;
5539 /* loop through checking if we have a matching
5540 name and then return the associated value */
5541 while (name_len > 0) {
5546 le16_to_cpu(temp_fea->value_len);
5547 /* BB validate that value_len falls within SMB,
5548 even though maximum for name_len is 255 */
5549 if (memcmp(temp_fea->name, ea_name,
5550 temp_fea->name_len) == 0) {
5553 /* account for prefix user. and trailing null */
5554 if (rc <= (int)buf_size) {
5556 temp_fea->name+temp_fea->name_len+1,
5558 /* ea values, unlike ea
5561 } else if (buf_size == 0) {
5562 /* skip copy - calc size only */
5564 /* stop before overrun buffer */
5569 name_len -= temp_fea->name_len;
5570 temp_ptr += temp_fea->name_len;
5571 /* account for trailing null */
5574 name_len -= value_len;
5575 temp_ptr += value_len;
5576 /* No trailing null to account for in
5577 value_len. Go on to next EA */
5578 temp_fea = (struct fea *)temp_ptr;
5583 cifs_buf_release(pSMB);
5591 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5592 const char *ea_name, const void *ea_value,
5593 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5596 struct smb_com_transaction2_spi_req *pSMB = NULL;
5597 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5598 struct fealist *parm_data;
5601 int bytes_returned = 0;
5602 __u16 params, param_offset, byte_count, offset, count;
5604 cFYI(1, ("In SetEA"));
5606 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5611 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5613 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5614 PATH_MAX, nls_codepage, remap);
5615 name_len++; /* trailing null */
5617 } else { /* BB improve the check for buffer overruns BB */
5618 name_len = strnlen(fileName, PATH_MAX);
5619 name_len++; /* trailing null */
5620 strncpy(pSMB->FileName, fileName, name_len);
5623 params = 6 + name_len;
5625 /* done calculating parms using name_len of file name,
5626 now use name_len to calculate length of ea name
5627 we are going to create in the inode xattrs */
5628 if (ea_name == NULL)
5631 name_len = strnlen(ea_name, 255);
5633 count = sizeof(*parm_data) + ea_value_len + name_len;
5634 pSMB->MaxParameterCount = cpu_to_le16(2);
5635 /* BB find max SMB PDU from sess */
5636 pSMB->MaxDataCount = cpu_to_le16(1000);
5637 pSMB->MaxSetupCount = 0;
5641 pSMB->Reserved2 = 0;
5642 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5643 InformationLevel) - 4;
5644 offset = param_offset + params;
5645 pSMB->InformationLevel =
5646 cpu_to_le16(SMB_SET_FILE_EA);
5649 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5651 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5652 pSMB->DataOffset = cpu_to_le16(offset);
5653 pSMB->SetupCount = 1;
5654 pSMB->Reserved3 = 0;
5655 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5656 byte_count = 3 /* pad */ + params + count;
5657 pSMB->DataCount = cpu_to_le16(count);
5658 parm_data->list_len = cpu_to_le32(count);
5659 parm_data->list[0].EA_flags = 0;
5660 /* we checked above that name len is less than 255 */
5661 parm_data->list[0].name_len = (__u8)name_len;
5662 /* EA names are always ASCII */
5664 strncpy(parm_data->list[0].name, ea_name, name_len);
5665 parm_data->list[0].name[name_len] = 0;
5666 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5667 /* caller ensures that ea_value_len is less than 64K but
5668 we need to ensure that it fits within the smb */
5670 /*BB add length check to see if it would fit in
5671 negotiated SMB buffer size BB */
5672 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5674 memcpy(parm_data->list[0].name+name_len+1,
5675 ea_value, ea_value_len);
5677 pSMB->TotalDataCount = pSMB->DataCount;
5678 pSMB->ParameterCount = cpu_to_le16(params);
5679 pSMB->TotalParameterCount = pSMB->ParameterCount;
5680 pSMB->Reserved4 = 0;
5681 pSMB->hdr.smb_buf_length += byte_count;
5682 pSMB->ByteCount = cpu_to_le16(byte_count);
5683 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5684 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5686 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5688 cifs_buf_release(pSMB);