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 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
532 /* even though we do not use raw we might as well set this
533 accurately, in case we ever find a need for it */
534 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
535 server->maxRw = 0xFF00;
536 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
538 server->maxRw = 0;/* we do not need to use raw anyway */
539 server->capabilities = CAP_MPX_MODE;
541 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
543 /* OS/2 often does not set timezone therefore
544 * we must use server time to calc time zone.
545 * Could deviate slightly from the right zone.
546 * Smallest defined timezone difference is 15 minutes
547 * (i.e. Nepal). Rounding up/down is done to match
550 int val, seconds, remain, result;
551 struct timespec ts, utc;
553 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
554 le16_to_cpu(rsp->SrvTime.Time));
555 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
556 (int)ts.tv_sec, (int)utc.tv_sec,
557 (int)(utc.tv_sec - ts.tv_sec)));
558 val = (int)(utc.tv_sec - ts.tv_sec);
560 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
561 remain = seconds % MIN_TZ_ADJ;
562 if (remain >= (MIN_TZ_ADJ / 2))
563 result += MIN_TZ_ADJ;
566 server->timeAdj = result;
568 server->timeAdj = (int)tmp;
569 server->timeAdj *= 60; /* also in seconds */
571 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
574 /* BB get server time for time conversions and add
575 code to use it and timezone since this is not UTC */
577 if (rsp->EncryptionKeyLength ==
578 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
579 memcpy(server->cryptKey, rsp->EncryptionKey,
580 CIFS_CRYPTO_KEY_SIZE);
581 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
582 rc = -EIO; /* need cryptkey unless plain text */
586 cFYI(1, ("LANMAN negotiated"));
587 /* we will not end up setting signing flags - as no signing
588 was in LANMAN and server did not return the flags on */
590 #else /* weak security disabled */
591 } else if (pSMBr->hdr.WordCount == 13) {
592 cERROR(1, ("mount failed, cifs module not built "
593 "with CIFS_WEAK_PW_HASH support"));
595 #endif /* WEAK_PW_HASH */
597 } else if (pSMBr->hdr.WordCount != 17) {
602 /* else wct == 17 NTLM */
603 server->secMode = pSMBr->SecurityMode;
604 if ((server->secMode & SECMODE_USER) == 0)
605 cFYI(1, ("share mode security"));
607 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
608 #ifdef CONFIG_CIFS_WEAK_PW_HASH
609 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
610 #endif /* CIFS_WEAK_PW_HASH */
611 cERROR(1, ("Server requests plain text password"
612 " but client support disabled"));
614 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
615 server->secType = NTLMv2;
616 else if (secFlags & CIFSSEC_MAY_NTLM)
617 server->secType = NTLM;
618 else if (secFlags & CIFSSEC_MAY_NTLMV2)
619 server->secType = NTLMv2;
620 else if (secFlags & CIFSSEC_MAY_KRB5)
621 server->secType = Kerberos;
622 else if (secFlags & CIFSSEC_MAY_LANMAN)
623 server->secType = LANMAN;
624 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
625 else if (secFlags & CIFSSEC_MAY_PLNTXT)
630 cERROR(1, ("Invalid security type"));
633 /* else ... any others ...? */
635 /* one byte, so no need to convert this or EncryptionKeyLen from
637 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
638 /* probably no need to store and check maxvcs */
639 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
640 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
641 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
642 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
643 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
644 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
645 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
646 server->timeAdj *= 60;
647 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
648 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
649 CIFS_CRYPTO_KEY_SIZE);
650 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
651 && (pSMBr->EncryptionKeyLength == 0)) {
652 /* decode security blob */
653 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
654 rc = -EIO; /* no crypt key only if plain text pwd */
658 /* BB might be helpful to save off the domain of server here */
660 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
661 (server->capabilities & CAP_EXTENDED_SECURITY)) {
662 count = pSMBr->ByteCount;
667 read_lock(&cifs_tcp_ses_lock);
668 if (server->srv_count > 1) {
669 read_unlock(&cifs_tcp_ses_lock);
670 if (memcmp(server->server_GUID,
671 pSMBr->u.extended_response.
673 cFYI(1, ("server UID changed"));
674 memcpy(server->server_GUID,
675 pSMBr->u.extended_response.GUID,
679 read_unlock(&cifs_tcp_ses_lock);
680 memcpy(server->server_GUID,
681 pSMBr->u.extended_response.GUID, 16);
685 server->secType = RawNTLMSSP;
687 rc = decode_negTokenInit(pSMBr->u.extended_response.
697 server->capabilities &= ~CAP_EXTENDED_SECURITY;
699 #ifdef CONFIG_CIFS_WEAK_PW_HASH
702 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
703 /* MUST_SIGN already includes the MAY_SIGN FLAG
704 so if this is zero it means that signing is disabled */
705 cFYI(1, ("Signing disabled"));
706 if (server->secMode & SECMODE_SIGN_REQUIRED) {
707 cERROR(1, ("Server requires "
708 "packet signing to be enabled in "
709 "/proc/fs/cifs/SecurityFlags."));
713 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
714 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
715 /* signing required */
716 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
717 if ((server->secMode &
718 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
720 ("signing required but server lacks support"));
723 server->secMode |= SECMODE_SIGN_REQUIRED;
725 /* signing optional ie CIFSSEC_MAY_SIGN */
726 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
728 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
732 cifs_buf_release(pSMB);
734 cFYI(1, ("negprot rc %d", rc));
739 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
741 struct smb_hdr *smb_buffer;
744 cFYI(1, ("In tree disconnect"));
746 /* BB: do we need to check this? These should never be NULL. */
747 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
751 * No need to return error on this operation if tid invalidated and
752 * closed on server already e.g. due to tcp session crashing. Also,
753 * the tcon is no longer on the list, so no need to take lock before
756 if (tcon->need_reconnect)
759 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
760 (void **)&smb_buffer);
764 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
766 cFYI(1, ("Tree disconnect failed %d", rc));
768 /* No need to return error on this operation if tid invalidated and
769 closed on server already e.g. due to tcp session crashing */
777 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
779 LOGOFF_ANDX_REQ *pSMB;
782 cFYI(1, ("In SMBLogoff for session disconnect"));
785 * BB: do we need to check validity of ses and server? They should
786 * always be valid since we have an active reference. If not, that
787 * should probably be a BUG()
789 if (!ses || !ses->server)
793 if (ses->need_reconnect)
794 goto session_already_dead; /* no need to send SMBlogoff if uid
795 already closed due to reconnect */
796 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
802 pSMB->hdr.Mid = GetNextMid(ses->server);
804 if (ses->server->secMode &
805 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
806 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
808 pSMB->hdr.Uid = ses->Suid;
810 pSMB->AndXCommand = 0xFF;
811 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
812 session_already_dead:
815 /* if session dead then we do not need to do ulogoff,
816 since server closed smb session, no sense reporting
824 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
825 __u16 type, const struct nls_table *nls_codepage, int remap)
827 TRANSACTION2_SPI_REQ *pSMB = NULL;
828 TRANSACTION2_SPI_RSP *pSMBr = NULL;
829 struct unlink_psx_rq *pRqD;
832 int bytes_returned = 0;
833 __u16 params, param_offset, offset, byte_count;
835 cFYI(1, ("In POSIX delete"));
837 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
842 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
844 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
845 PATH_MAX, nls_codepage, remap);
846 name_len++; /* trailing null */
848 } else { /* BB add path length overrun check */
849 name_len = strnlen(fileName, PATH_MAX);
850 name_len++; /* trailing null */
851 strncpy(pSMB->FileName, fileName, name_len);
854 params = 6 + name_len;
855 pSMB->MaxParameterCount = cpu_to_le16(2);
856 pSMB->MaxDataCount = 0; /* BB double check this with jra */
857 pSMB->MaxSetupCount = 0;
862 param_offset = offsetof(struct smb_com_transaction2_spi_req,
863 InformationLevel) - 4;
864 offset = param_offset + params;
866 /* Setup pointer to Request Data (inode type) */
867 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
868 pRqD->type = cpu_to_le16(type);
869 pSMB->ParameterOffset = cpu_to_le16(param_offset);
870 pSMB->DataOffset = cpu_to_le16(offset);
871 pSMB->SetupCount = 1;
873 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
874 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
876 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
877 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878 pSMB->ParameterCount = cpu_to_le16(params);
879 pSMB->TotalParameterCount = pSMB->ParameterCount;
880 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
882 pSMB->hdr.smb_buf_length += byte_count;
883 pSMB->ByteCount = cpu_to_le16(byte_count);
884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887 cFYI(1, ("Posix delete returned %d", rc));
888 cifs_buf_release(pSMB);
890 cifs_stats_inc(&tcon->num_deletes);
899 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
900 const struct nls_table *nls_codepage, int remap)
902 DELETE_FILE_REQ *pSMB = NULL;
903 DELETE_FILE_RSP *pSMBr = NULL;
909 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
914 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
916 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
917 PATH_MAX, nls_codepage, remap);
918 name_len++; /* trailing null */
920 } else { /* BB improve check for buffer overruns BB */
921 name_len = strnlen(fileName, PATH_MAX);
922 name_len++; /* trailing null */
923 strncpy(pSMB->fileName, fileName, name_len);
925 pSMB->SearchAttributes =
926 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
927 pSMB->BufferFormat = 0x04;
928 pSMB->hdr.smb_buf_length += name_len + 1;
929 pSMB->ByteCount = cpu_to_le16(name_len + 1);
930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
932 cifs_stats_inc(&tcon->num_deletes);
934 cFYI(1, ("Error in RMFile = %d", rc));
936 cifs_buf_release(pSMB);
944 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
945 const struct nls_table *nls_codepage, int remap)
947 DELETE_DIRECTORY_REQ *pSMB = NULL;
948 DELETE_DIRECTORY_RSP *pSMBr = NULL;
953 cFYI(1, ("In CIFSSMBRmDir"));
955 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
962 PATH_MAX, nls_codepage, remap);
963 name_len++; /* trailing null */
965 } else { /* BB improve check for buffer overruns BB */
966 name_len = strnlen(dirName, PATH_MAX);
967 name_len++; /* trailing null */
968 strncpy(pSMB->DirName, dirName, name_len);
971 pSMB->BufferFormat = 0x04;
972 pSMB->hdr.smb_buf_length += name_len + 1;
973 pSMB->ByteCount = cpu_to_le16(name_len + 1);
974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
976 cifs_stats_inc(&tcon->num_rmdirs);
978 cFYI(1, ("Error in RMDir = %d", rc));
980 cifs_buf_release(pSMB);
987 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
988 const char *name, const struct nls_table *nls_codepage, int remap)
991 CREATE_DIRECTORY_REQ *pSMB = NULL;
992 CREATE_DIRECTORY_RSP *pSMBr = NULL;
996 cFYI(1, ("In CIFSSMBMkDir"));
998 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1004 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1005 PATH_MAX, nls_codepage, remap);
1006 name_len++; /* trailing null */
1008 } else { /* BB improve check for buffer overruns BB */
1009 name_len = strnlen(name, PATH_MAX);
1010 name_len++; /* trailing null */
1011 strncpy(pSMB->DirName, name, name_len);
1014 pSMB->BufferFormat = 0x04;
1015 pSMB->hdr.smb_buf_length += name_len + 1;
1016 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1017 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1018 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1019 cifs_stats_inc(&tcon->num_mkdirs);
1021 cFYI(1, ("Error in Mkdir = %d", rc));
1023 cifs_buf_release(pSMB);
1030 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1031 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1032 __u32 *pOplock, const char *name,
1033 const struct nls_table *nls_codepage, int remap)
1035 TRANSACTION2_SPI_REQ *pSMB = NULL;
1036 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1039 int bytes_returned = 0;
1040 __u16 params, param_offset, offset, byte_count, count;
1041 OPEN_PSX_REQ *pdata;
1042 OPEN_PSX_RSP *psx_rsp;
1044 cFYI(1, ("In POSIX Create"));
1046 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1051 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1053 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1054 PATH_MAX, nls_codepage, remap);
1055 name_len++; /* trailing null */
1057 } else { /* BB improve the check for buffer overruns BB */
1058 name_len = strnlen(name, PATH_MAX);
1059 name_len++; /* trailing null */
1060 strncpy(pSMB->FileName, name, name_len);
1063 params = 6 + name_len;
1064 count = sizeof(OPEN_PSX_REQ);
1065 pSMB->MaxParameterCount = cpu_to_le16(2);
1066 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1067 pSMB->MaxSetupCount = 0;
1071 pSMB->Reserved2 = 0;
1072 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1073 InformationLevel) - 4;
1074 offset = param_offset + params;
1075 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1076 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1077 pdata->Permissions = cpu_to_le64(mode);
1078 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1079 pdata->OpenFlags = cpu_to_le32(*pOplock);
1080 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1081 pSMB->DataOffset = cpu_to_le16(offset);
1082 pSMB->SetupCount = 1;
1083 pSMB->Reserved3 = 0;
1084 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1085 byte_count = 3 /* pad */ + params + count;
1087 pSMB->DataCount = cpu_to_le16(count);
1088 pSMB->ParameterCount = cpu_to_le16(params);
1089 pSMB->TotalDataCount = pSMB->DataCount;
1090 pSMB->TotalParameterCount = pSMB->ParameterCount;
1091 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1092 pSMB->Reserved4 = 0;
1093 pSMB->hdr.smb_buf_length += byte_count;
1094 pSMB->ByteCount = cpu_to_le16(byte_count);
1095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1098 cFYI(1, ("Posix create returned %d", rc));
1099 goto psx_create_err;
1102 cFYI(1, ("copying inode info"));
1103 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1105 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1106 rc = -EIO; /* bad smb */
1107 goto psx_create_err;
1110 /* copy return information to pRetData */
1111 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1112 + le16_to_cpu(pSMBr->t2.DataOffset));
1114 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1116 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1117 /* Let caller know file was created so we can set the mode. */
1118 /* Do we care about the CreateAction in any other cases? */
1119 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1120 *pOplock |= CIFS_CREATE_ACTION;
1121 /* check to make sure response data is there */
1122 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1123 pRetData->Type = cpu_to_le32(-1); /* unknown */
1124 cFYI(DBG2, ("unknown type"));
1126 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1127 + sizeof(FILE_UNIX_BASIC_INFO)) {
1128 cERROR(1, ("Open response data too small"));
1129 pRetData->Type = cpu_to_le32(-1);
1130 goto psx_create_err;
1132 memcpy((char *) pRetData,
1133 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1134 sizeof(FILE_UNIX_BASIC_INFO));
1138 cifs_buf_release(pSMB);
1140 cifs_stats_inc(&tcon->num_mkdirs);
1148 static __u16 convert_disposition(int disposition)
1152 switch (disposition) {
1153 case FILE_SUPERSEDE:
1154 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1157 ofun = SMBOPEN_OAPPEND;
1160 ofun = SMBOPEN_OCREATE;
1163 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1165 case FILE_OVERWRITE:
1166 ofun = SMBOPEN_OTRUNC;
1168 case FILE_OVERWRITE_IF:
1169 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1172 cFYI(1, ("unknown disposition %d", disposition));
1173 ofun = SMBOPEN_OAPPEND; /* regular open */
1179 access_flags_to_smbopen_mode(const int access_flags)
1181 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1183 if (masked_flags == GENERIC_READ)
1184 return SMBOPEN_READ;
1185 else if (masked_flags == GENERIC_WRITE)
1186 return SMBOPEN_WRITE;
1188 /* just go for read/write */
1189 return SMBOPEN_READWRITE;
1193 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1194 const char *fileName, const int openDisposition,
1195 const int access_flags, const int create_options, __u16 *netfid,
1196 int *pOplock, FILE_ALL_INFO *pfile_info,
1197 const struct nls_table *nls_codepage, int remap)
1200 OPENX_REQ *pSMB = NULL;
1201 OPENX_RSP *pSMBr = NULL;
1207 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1212 pSMB->AndXCommand = 0xFF; /* none */
1214 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1215 count = 1; /* account for one byte pad to word boundary */
1217 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1218 fileName, PATH_MAX, nls_codepage, remap);
1219 name_len++; /* trailing null */
1221 } else { /* BB improve check for buffer overruns BB */
1222 count = 0; /* no pad */
1223 name_len = strnlen(fileName, PATH_MAX);
1224 name_len++; /* trailing null */
1225 strncpy(pSMB->fileName, fileName, name_len);
1227 if (*pOplock & REQ_OPLOCK)
1228 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1229 else if (*pOplock & REQ_BATCHOPLOCK)
1230 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1232 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1233 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1234 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1235 /* set file as system file if special file such
1236 as fifo and server expecting SFU style and
1237 no Unix extensions */
1239 if (create_options & CREATE_OPTION_SPECIAL)
1240 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1241 else /* BB FIXME BB */
1242 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1244 if (create_options & CREATE_OPTION_READONLY)
1245 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1248 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1249 CREATE_OPTIONS_MASK); */
1250 /* BB FIXME END BB */
1252 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1253 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1255 pSMB->hdr.smb_buf_length += count;
1257 pSMB->ByteCount = cpu_to_le16(count);
1258 /* long_op set to 1 to allow for oplock break timeouts */
1259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1260 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1261 cifs_stats_inc(&tcon->num_opens);
1263 cFYI(1, ("Error in Open = %d", rc));
1265 /* BB verify if wct == 15 */
1267 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1269 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1270 /* Let caller know file was created so we can set the mode. */
1271 /* Do we care about the CreateAction in any other cases? */
1273 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1274 *pOplock |= CIFS_CREATE_ACTION; */
1278 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1279 pfile_info->LastAccessTime = 0; /* BB fixme */
1280 pfile_info->LastWriteTime = 0; /* BB fixme */
1281 pfile_info->ChangeTime = 0; /* BB fixme */
1282 pfile_info->Attributes =
1283 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1284 /* the file_info buf is endian converted by caller */
1285 pfile_info->AllocationSize =
1286 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1287 pfile_info->EndOfFile = pfile_info->AllocationSize;
1288 pfile_info->NumberOfLinks = cpu_to_le32(1);
1289 pfile_info->DeletePending = 0;
1293 cifs_buf_release(pSMB);
1300 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1301 const char *fileName, const int openDisposition,
1302 const int access_flags, const int create_options, __u16 *netfid,
1303 int *pOplock, FILE_ALL_INFO *pfile_info,
1304 const struct nls_table *nls_codepage, int remap)
1307 OPEN_REQ *pSMB = NULL;
1308 OPEN_RSP *pSMBr = NULL;
1314 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1319 pSMB->AndXCommand = 0xFF; /* none */
1321 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1322 count = 1; /* account for one byte pad to word boundary */
1324 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1325 fileName, PATH_MAX, nls_codepage, remap);
1326 name_len++; /* trailing null */
1328 pSMB->NameLength = cpu_to_le16(name_len);
1329 } else { /* BB improve check for buffer overruns BB */
1330 count = 0; /* no pad */
1331 name_len = strnlen(fileName, PATH_MAX);
1332 name_len++; /* trailing null */
1333 pSMB->NameLength = cpu_to_le16(name_len);
1334 strncpy(pSMB->fileName, fileName, name_len);
1336 if (*pOplock & REQ_OPLOCK)
1337 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1338 else if (*pOplock & REQ_BATCHOPLOCK)
1339 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1340 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1341 pSMB->AllocationSize = 0;
1342 /* set file as system file if special file such
1343 as fifo and server expecting SFU style and
1344 no Unix extensions */
1345 if (create_options & CREATE_OPTION_SPECIAL)
1346 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1348 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1350 /* XP does not handle ATTR_POSIX_SEMANTICS */
1351 /* but it helps speed up case sensitive checks for other
1352 servers such as Samba */
1353 if (tcon->ses->capabilities & CAP_UNIX)
1354 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1356 if (create_options & CREATE_OPTION_READONLY)
1357 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1359 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1360 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1361 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1362 /* BB Expirement with various impersonation levels and verify */
1363 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1364 pSMB->SecurityFlags =
1365 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1368 pSMB->hdr.smb_buf_length += count;
1370 pSMB->ByteCount = cpu_to_le16(count);
1371 /* long_op set to 1 to allow for oplock break timeouts */
1372 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1373 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1374 cifs_stats_inc(&tcon->num_opens);
1376 cFYI(1, ("Error in Open = %d", rc));
1378 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1379 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1380 /* Let caller know file was created so we can set the mode. */
1381 /* Do we care about the CreateAction in any other cases? */
1382 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1383 *pOplock |= CIFS_CREATE_ACTION;
1385 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1386 36 /* CreationTime to Attributes */);
1387 /* the file_info buf is endian converted by caller */
1388 pfile_info->AllocationSize = pSMBr->AllocationSize;
1389 pfile_info->EndOfFile = pSMBr->EndOfFile;
1390 pfile_info->NumberOfLinks = cpu_to_le32(1);
1391 pfile_info->DeletePending = 0;
1395 cifs_buf_release(pSMB);
1402 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1403 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1404 char **buf, int *pbuf_type)
1407 READ_REQ *pSMB = NULL;
1408 READ_RSP *pSMBr = NULL;
1409 char *pReadData = NULL;
1411 int resp_buf_type = 0;
1414 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1415 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1418 wct = 10; /* old style read */
1419 if ((lseek >> 32) > 0) {
1420 /* can not handle this big offset for old */
1426 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1430 /* tcon and ses pointer are checked in smb_init */
1431 if (tcon->ses->server == NULL)
1432 return -ECONNABORTED;
1434 pSMB->AndXCommand = 0xFF; /* none */
1436 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1438 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1440 pSMB->Remaining = 0;
1441 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1442 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1444 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1446 /* old style read */
1447 struct smb_com_readx_req *pSMBW =
1448 (struct smb_com_readx_req *)pSMB;
1449 pSMBW->ByteCount = 0;
1452 iov[0].iov_base = (char *)pSMB;
1453 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1454 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1455 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1456 cifs_stats_inc(&tcon->num_reads);
1457 pSMBr = (READ_RSP *)iov[0].iov_base;
1459 cERROR(1, ("Send error in read = %d", rc));
1461 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1462 data_length = data_length << 16;
1463 data_length += le16_to_cpu(pSMBr->DataLength);
1464 *nbytes = data_length;
1466 /*check that DataLength would not go beyond end of SMB */
1467 if ((data_length > CIFSMaxBufSize)
1468 || (data_length > count)) {
1469 cFYI(1, ("bad length %d for count %d",
1470 data_length, count));
1474 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1475 le16_to_cpu(pSMBr->DataOffset);
1476 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1477 cERROR(1,("Faulting on read rc = %d",rc));
1479 }*/ /* can not use copy_to_user when using page cache*/
1481 memcpy(*buf, pReadData, data_length);
1485 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1487 if (resp_buf_type == CIFS_SMALL_BUFFER)
1488 cifs_small_buf_release(iov[0].iov_base);
1489 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1490 cifs_buf_release(iov[0].iov_base);
1491 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1492 /* return buffer to caller to free */
1493 *buf = iov[0].iov_base;
1494 if (resp_buf_type == CIFS_SMALL_BUFFER)
1495 *pbuf_type = CIFS_SMALL_BUFFER;
1496 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1497 *pbuf_type = CIFS_LARGE_BUFFER;
1498 } /* else no valid buffer on return - leave as null */
1500 /* Note: On -EAGAIN error only caller can retry on handle based calls
1501 since file handle passed in no longer valid */
1507 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1508 const int netfid, const unsigned int count,
1509 const __u64 offset, unsigned int *nbytes, const char *buf,
1510 const char __user *ubuf, const int long_op)
1513 WRITE_REQ *pSMB = NULL;
1514 WRITE_RSP *pSMBr = NULL;
1515 int bytes_returned, wct;
1519 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1520 if (tcon->ses == NULL)
1521 return -ECONNABORTED;
1523 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1527 if ((offset >> 32) > 0) {
1528 /* can not handle big offset for old srv */
1533 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1537 /* tcon and ses pointer are checked in smb_init */
1538 if (tcon->ses->server == NULL)
1539 return -ECONNABORTED;
1541 pSMB->AndXCommand = 0xFF; /* none */
1543 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1545 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1547 pSMB->Reserved = 0xFFFFFFFF;
1548 pSMB->WriteMode = 0;
1549 pSMB->Remaining = 0;
1551 /* Can increase buffer size if buffer is big enough in some cases ie we
1552 can send more if LARGE_WRITE_X capability returned by the server and if
1553 our buffer is big enough or if we convert to iovecs on socket writes
1554 and eliminate the copy to the CIFS buffer */
1555 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1556 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1558 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1562 if (bytes_sent > count)
1565 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1567 memcpy(pSMB->Data, buf, bytes_sent);
1569 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1570 cifs_buf_release(pSMB);
1573 } else if (count != 0) {
1575 cifs_buf_release(pSMB);
1577 } /* else setting file size with write of zero bytes */
1579 byte_count = bytes_sent + 1; /* pad */
1580 else /* wct == 12 */
1581 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1583 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1584 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1585 pSMB->hdr.smb_buf_length += byte_count;
1588 pSMB->ByteCount = cpu_to_le16(byte_count);
1589 else { /* old style write has byte count 4 bytes earlier
1591 struct smb_com_writex_req *pSMBW =
1592 (struct smb_com_writex_req *)pSMB;
1593 pSMBW->ByteCount = cpu_to_le16(byte_count);
1596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1597 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1598 cifs_stats_inc(&tcon->num_writes);
1600 cFYI(1, ("Send error in write = %d", rc));
1603 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1604 *nbytes = (*nbytes) << 16;
1605 *nbytes += le16_to_cpu(pSMBr->Count);
1608 cifs_buf_release(pSMB);
1610 /* Note: On -EAGAIN error only caller can retry on handle based calls
1611 since file handle passed in no longer valid */
1617 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1618 const int netfid, const unsigned int count,
1619 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1620 int n_vec, const int long_op)
1623 WRITE_REQ *pSMB = NULL;
1626 int resp_buf_type = 0;
1628 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1630 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1634 if ((offset >> 32) > 0) {
1635 /* can not handle big offset for old srv */
1639 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1642 /* tcon and ses pointer are checked in smb_init */
1643 if (tcon->ses->server == NULL)
1644 return -ECONNABORTED;
1646 pSMB->AndXCommand = 0xFF; /* none */
1648 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1650 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1651 pSMB->Reserved = 0xFFFFFFFF;
1652 pSMB->WriteMode = 0;
1653 pSMB->Remaining = 0;
1656 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1658 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1659 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1660 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1662 pSMB->hdr.smb_buf_length += count+1;
1663 else /* wct == 12 */
1664 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1666 pSMB->ByteCount = cpu_to_le16(count + 1);
1667 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1668 struct smb_com_writex_req *pSMBW =
1669 (struct smb_com_writex_req *)pSMB;
1670 pSMBW->ByteCount = cpu_to_le16(count + 5);
1672 iov[0].iov_base = pSMB;
1674 iov[0].iov_len = smb_hdr_len + 4;
1675 else /* wct == 12 pad bigger by four bytes */
1676 iov[0].iov_len = smb_hdr_len + 8;
1679 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1681 cifs_stats_inc(&tcon->num_writes);
1683 cFYI(1, ("Send error Write2 = %d", rc));
1685 } else if (resp_buf_type == 0) {
1686 /* presumably this can not happen, but best to be safe */
1690 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1691 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1692 *nbytes = (*nbytes) << 16;
1693 *nbytes += le16_to_cpu(pSMBr->Count);
1696 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1697 if (resp_buf_type == CIFS_SMALL_BUFFER)
1698 cifs_small_buf_release(iov[0].iov_base);
1699 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1700 cifs_buf_release(iov[0].iov_base);
1702 /* Note: On -EAGAIN error only caller can retry on handle based calls
1703 since file handle passed in no longer valid */
1710 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1711 const __u16 smb_file_id, const __u64 len,
1712 const __u64 offset, const __u32 numUnlock,
1713 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1716 LOCK_REQ *pSMB = NULL;
1717 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1722 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1723 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1728 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1729 timeout = CIFS_ASYNC_OP; /* no response expected */
1731 } else if (waitFlag) {
1732 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1733 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1738 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1739 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1740 pSMB->LockType = lockType;
1741 pSMB->AndXCommand = 0xFF; /* none */
1742 pSMB->Fid = smb_file_id; /* netfid stays le */
1744 if ((numLock != 0) || (numUnlock != 0)) {
1745 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1746 /* BB where to store pid high? */
1747 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1748 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1749 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1750 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1751 count = sizeof(LOCKING_ANDX_RANGE);
1756 pSMB->hdr.smb_buf_length += count;
1757 pSMB->ByteCount = cpu_to_le16(count);
1760 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1761 (struct smb_hdr *) pSMB, &bytes_returned);
1762 cifs_small_buf_release(pSMB);
1764 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1766 /* SMB buffer freed by function above */
1768 cifs_stats_inc(&tcon->num_locks);
1770 cFYI(1, ("Send error in Lock = %d", rc));
1772 /* Note: On -EAGAIN error only caller can retry on handle based calls
1773 since file handle passed in no longer valid */
1778 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1779 const __u16 smb_file_id, const int get_flag, const __u64 len,
1780 struct file_lock *pLockData, const __u16 lock_type,
1781 const bool waitFlag)
1783 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1784 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1785 struct cifs_posix_lock *parm_data;
1788 int bytes_returned = 0;
1789 int resp_buf_type = 0;
1790 __u16 params, param_offset, offset, byte_count, count;
1793 cFYI(1, ("Posix Lock"));
1795 if (pLockData == NULL)
1798 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1803 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1806 pSMB->MaxSetupCount = 0;
1809 pSMB->Reserved2 = 0;
1810 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1811 offset = param_offset + params;
1813 count = sizeof(struct cifs_posix_lock);
1814 pSMB->MaxParameterCount = cpu_to_le16(2);
1815 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1816 pSMB->SetupCount = 1;
1817 pSMB->Reserved3 = 0;
1819 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1821 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1822 byte_count = 3 /* pad */ + params + count;
1823 pSMB->DataCount = cpu_to_le16(count);
1824 pSMB->ParameterCount = cpu_to_le16(params);
1825 pSMB->TotalDataCount = pSMB->DataCount;
1826 pSMB->TotalParameterCount = pSMB->ParameterCount;
1827 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1828 parm_data = (struct cifs_posix_lock *)
1829 (((char *) &pSMB->hdr.Protocol) + offset);
1831 parm_data->lock_type = cpu_to_le16(lock_type);
1833 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1834 parm_data->lock_flags = cpu_to_le16(1);
1835 pSMB->Timeout = cpu_to_le32(-1);
1839 parm_data->pid = cpu_to_le32(current->tgid);
1840 parm_data->start = cpu_to_le64(pLockData->fl_start);
1841 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1843 pSMB->DataOffset = cpu_to_le16(offset);
1844 pSMB->Fid = smb_file_id;
1845 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1846 pSMB->Reserved4 = 0;
1847 pSMB->hdr.smb_buf_length += byte_count;
1848 pSMB->ByteCount = cpu_to_le16(byte_count);
1850 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1851 (struct smb_hdr *) pSMBr, &bytes_returned);
1853 iov[0].iov_base = (char *)pSMB;
1854 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1855 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1856 &resp_buf_type, timeout);
1857 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1858 not try to free it twice below on exit */
1859 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1863 cFYI(1, ("Send error in Posix Lock = %d", rc));
1864 } else if (get_flag) {
1865 /* lock structure can be returned on get */
1868 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1870 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1871 rc = -EIO; /* bad smb */
1874 if (pLockData == NULL) {
1878 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1879 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1880 if (data_count < sizeof(struct cifs_posix_lock)) {
1884 parm_data = (struct cifs_posix_lock *)
1885 ((char *)&pSMBr->hdr.Protocol + data_offset);
1886 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1887 pLockData->fl_type = F_UNLCK;
1892 cifs_small_buf_release(pSMB);
1894 if (resp_buf_type == CIFS_SMALL_BUFFER)
1895 cifs_small_buf_release(iov[0].iov_base);
1896 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1897 cifs_buf_release(iov[0].iov_base);
1899 /* Note: On -EAGAIN error only caller can retry on handle based calls
1900 since file handle passed in no longer valid */
1907 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1910 CLOSE_REQ *pSMB = NULL;
1911 cFYI(1, ("In CIFSSMBClose"));
1913 /* do not retry on dead session on close */
1914 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1920 pSMB->FileID = (__u16) smb_file_id;
1921 pSMB->LastWriteTime = 0xFFFFFFFF;
1922 pSMB->ByteCount = 0;
1923 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1924 cifs_stats_inc(&tcon->num_closes);
1927 /* EINTR is expected when user ctl-c to kill app */
1928 cERROR(1, ("Send error in Close = %d", rc));
1932 /* Since session is dead, file will be closed on server already */
1940 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1941 const char *fromName, const char *toName,
1942 const struct nls_table *nls_codepage, int remap)
1945 RENAME_REQ *pSMB = NULL;
1946 RENAME_RSP *pSMBr = NULL;
1948 int name_len, name_len2;
1951 cFYI(1, ("In CIFSSMBRename"));
1953 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1958 pSMB->BufferFormat = 0x04;
1959 pSMB->SearchAttributes =
1960 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1963 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1965 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1966 PATH_MAX, nls_codepage, remap);
1967 name_len++; /* trailing null */
1969 pSMB->OldFileName[name_len] = 0x04; /* pad */
1970 /* protocol requires ASCII signature byte on Unicode string */
1971 pSMB->OldFileName[name_len + 1] = 0x00;
1973 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1974 toName, PATH_MAX, nls_codepage, remap);
1975 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1976 name_len2 *= 2; /* convert to bytes */
1977 } else { /* BB improve the check for buffer overruns BB */
1978 name_len = strnlen(fromName, PATH_MAX);
1979 name_len++; /* trailing null */
1980 strncpy(pSMB->OldFileName, fromName, name_len);
1981 name_len2 = strnlen(toName, PATH_MAX);
1982 name_len2++; /* trailing null */
1983 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1984 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1985 name_len2++; /* trailing null */
1986 name_len2++; /* signature byte */
1989 count = 1 /* 1st signature byte */ + name_len + name_len2;
1990 pSMB->hdr.smb_buf_length += count;
1991 pSMB->ByteCount = cpu_to_le16(count);
1993 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1994 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1995 cifs_stats_inc(&tcon->num_renames);
1997 cFYI(1, ("Send error in rename = %d", rc));
1999 cifs_buf_release(pSMB);
2007 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2008 int netfid, const char *target_name,
2009 const struct nls_table *nls_codepage, int remap)
2011 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2012 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2013 struct set_file_rename *rename_info;
2015 char dummy_string[30];
2017 int bytes_returned = 0;
2019 __u16 params, param_offset, offset, count, byte_count;
2021 cFYI(1, ("Rename to File by handle"));
2022 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2028 pSMB->MaxSetupCount = 0;
2032 pSMB->Reserved2 = 0;
2033 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2034 offset = param_offset + params;
2036 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2037 rename_info = (struct set_file_rename *) data_offset;
2038 pSMB->MaxParameterCount = cpu_to_le16(2);
2039 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2040 pSMB->SetupCount = 1;
2041 pSMB->Reserved3 = 0;
2042 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2043 byte_count = 3 /* pad */ + params;
2044 pSMB->ParameterCount = cpu_to_le16(params);
2045 pSMB->TotalParameterCount = pSMB->ParameterCount;
2046 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2047 pSMB->DataOffset = cpu_to_le16(offset);
2048 /* construct random name ".cifs_tmp<inodenum><mid>" */
2049 rename_info->overwrite = cpu_to_le32(1);
2050 rename_info->root_fid = 0;
2051 /* unicode only call */
2052 if (target_name == NULL) {
2053 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2054 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2055 dummy_string, 24, nls_codepage, remap);
2057 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2058 target_name, PATH_MAX, nls_codepage,
2061 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2062 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2063 byte_count += count;
2064 pSMB->DataCount = cpu_to_le16(count);
2065 pSMB->TotalDataCount = pSMB->DataCount;
2067 pSMB->InformationLevel =
2068 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2069 pSMB->Reserved4 = 0;
2070 pSMB->hdr.smb_buf_length += byte_count;
2071 pSMB->ByteCount = cpu_to_le16(byte_count);
2072 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2073 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2074 cifs_stats_inc(&pTcon->num_t2renames);
2076 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2078 cifs_buf_release(pSMB);
2080 /* Note: On -EAGAIN error only caller can retry on handle based calls
2081 since file handle passed in no longer valid */
2087 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2088 const __u16 target_tid, const char *toName, const int flags,
2089 const struct nls_table *nls_codepage, int remap)
2092 COPY_REQ *pSMB = NULL;
2093 COPY_RSP *pSMBr = NULL;
2095 int name_len, name_len2;
2098 cFYI(1, ("In CIFSSMBCopy"));
2100 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2105 pSMB->BufferFormat = 0x04;
2106 pSMB->Tid2 = target_tid;
2108 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2110 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2111 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2112 fromName, PATH_MAX, nls_codepage,
2114 name_len++; /* trailing null */
2116 pSMB->OldFileName[name_len] = 0x04; /* pad */
2117 /* protocol requires ASCII signature byte on Unicode string */
2118 pSMB->OldFileName[name_len + 1] = 0x00;
2120 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2121 toName, PATH_MAX, nls_codepage, remap);
2122 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2123 name_len2 *= 2; /* convert to bytes */
2124 } else { /* BB improve the check for buffer overruns BB */
2125 name_len = strnlen(fromName, PATH_MAX);
2126 name_len++; /* trailing null */
2127 strncpy(pSMB->OldFileName, fromName, name_len);
2128 name_len2 = strnlen(toName, PATH_MAX);
2129 name_len2++; /* trailing null */
2130 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2131 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2132 name_len2++; /* trailing null */
2133 name_len2++; /* signature byte */
2136 count = 1 /* 1st signature byte */ + name_len + name_len2;
2137 pSMB->hdr.smb_buf_length += count;
2138 pSMB->ByteCount = cpu_to_le16(count);
2140 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2141 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2143 cFYI(1, ("Send error in copy = %d with %d files copied",
2144 rc, le16_to_cpu(pSMBr->CopyCount)));
2146 cifs_buf_release(pSMB);
2155 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2156 const char *fromName, const char *toName,
2157 const struct nls_table *nls_codepage)
2159 TRANSACTION2_SPI_REQ *pSMB = NULL;
2160 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2163 int name_len_target;
2165 int bytes_returned = 0;
2166 __u16 params, param_offset, offset, byte_count;
2168 cFYI(1, ("In Symlink Unix style"));
2170 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2175 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2177 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2178 /* find define for this maxpathcomponent */
2180 name_len++; /* trailing null */
2183 } else { /* BB improve the check for buffer overruns BB */
2184 name_len = strnlen(fromName, PATH_MAX);
2185 name_len++; /* trailing null */
2186 strncpy(pSMB->FileName, fromName, name_len);
2188 params = 6 + name_len;
2189 pSMB->MaxSetupCount = 0;
2193 pSMB->Reserved2 = 0;
2194 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2195 InformationLevel) - 4;
2196 offset = param_offset + params;
2198 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2199 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2201 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2202 /* find define for this maxpathcomponent */
2204 name_len_target++; /* trailing null */
2205 name_len_target *= 2;
2206 } else { /* BB improve the check for buffer overruns BB */
2207 name_len_target = strnlen(toName, PATH_MAX);
2208 name_len_target++; /* trailing null */
2209 strncpy(data_offset, toName, name_len_target);
2212 pSMB->MaxParameterCount = cpu_to_le16(2);
2213 /* BB find exact max on data count below from sess */
2214 pSMB->MaxDataCount = cpu_to_le16(1000);
2215 pSMB->SetupCount = 1;
2216 pSMB->Reserved3 = 0;
2217 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2218 byte_count = 3 /* pad */ + params + name_len_target;
2219 pSMB->DataCount = cpu_to_le16(name_len_target);
2220 pSMB->ParameterCount = cpu_to_le16(params);
2221 pSMB->TotalDataCount = pSMB->DataCount;
2222 pSMB->TotalParameterCount = pSMB->ParameterCount;
2223 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2224 pSMB->DataOffset = cpu_to_le16(offset);
2225 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2226 pSMB->Reserved4 = 0;
2227 pSMB->hdr.smb_buf_length += byte_count;
2228 pSMB->ByteCount = cpu_to_le16(byte_count);
2229 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2230 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2231 cifs_stats_inc(&tcon->num_symlinks);
2233 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2235 cifs_buf_release(pSMB);
2238 goto createSymLinkRetry;
2244 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2245 const char *fromName, const char *toName,
2246 const struct nls_table *nls_codepage, int remap)
2248 TRANSACTION2_SPI_REQ *pSMB = NULL;
2249 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2252 int name_len_target;
2254 int bytes_returned = 0;
2255 __u16 params, param_offset, offset, byte_count;
2257 cFYI(1, ("In Create Hard link Unix style"));
2258 createHardLinkRetry:
2259 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2264 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2265 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2266 PATH_MAX, nls_codepage, remap);
2267 name_len++; /* trailing null */
2270 } else { /* BB improve the check for buffer overruns BB */
2271 name_len = strnlen(toName, PATH_MAX);
2272 name_len++; /* trailing null */
2273 strncpy(pSMB->FileName, toName, name_len);
2275 params = 6 + name_len;
2276 pSMB->MaxSetupCount = 0;
2280 pSMB->Reserved2 = 0;
2281 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2282 InformationLevel) - 4;
2283 offset = param_offset + params;
2285 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2286 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2288 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2289 nls_codepage, remap);
2290 name_len_target++; /* trailing null */
2291 name_len_target *= 2;
2292 } else { /* BB improve the check for buffer overruns BB */
2293 name_len_target = strnlen(fromName, PATH_MAX);
2294 name_len_target++; /* trailing null */
2295 strncpy(data_offset, fromName, name_len_target);
2298 pSMB->MaxParameterCount = cpu_to_le16(2);
2299 /* BB find exact max on data count below from sess*/
2300 pSMB->MaxDataCount = cpu_to_le16(1000);
2301 pSMB->SetupCount = 1;
2302 pSMB->Reserved3 = 0;
2303 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2304 byte_count = 3 /* pad */ + params + name_len_target;
2305 pSMB->ParameterCount = cpu_to_le16(params);
2306 pSMB->TotalParameterCount = pSMB->ParameterCount;
2307 pSMB->DataCount = cpu_to_le16(name_len_target);
2308 pSMB->TotalDataCount = pSMB->DataCount;
2309 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2310 pSMB->DataOffset = cpu_to_le16(offset);
2311 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2312 pSMB->Reserved4 = 0;
2313 pSMB->hdr.smb_buf_length += byte_count;
2314 pSMB->ByteCount = cpu_to_le16(byte_count);
2315 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2316 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2317 cifs_stats_inc(&tcon->num_hardlinks);
2319 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2321 cifs_buf_release(pSMB);
2323 goto createHardLinkRetry;
2329 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2330 const char *fromName, const char *toName,
2331 const struct nls_table *nls_codepage, int remap)
2334 NT_RENAME_REQ *pSMB = NULL;
2335 RENAME_RSP *pSMBr = NULL;
2337 int name_len, name_len2;
2340 cFYI(1, ("In CIFSCreateHardLink"));
2341 winCreateHardLinkRetry:
2343 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2348 pSMB->SearchAttributes =
2349 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2351 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2352 pSMB->ClusterCount = 0;
2354 pSMB->BufferFormat = 0x04;
2356 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2358 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2359 PATH_MAX, nls_codepage, remap);
2360 name_len++; /* trailing null */
2362 pSMB->OldFileName[name_len] = 0; /* pad */
2363 pSMB->OldFileName[name_len + 1] = 0x04;
2365 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2366 toName, PATH_MAX, nls_codepage, remap);
2367 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2368 name_len2 *= 2; /* convert to bytes */
2369 } else { /* BB improve the check for buffer overruns BB */
2370 name_len = strnlen(fromName, PATH_MAX);
2371 name_len++; /* trailing null */
2372 strncpy(pSMB->OldFileName, fromName, name_len);
2373 name_len2 = strnlen(toName, PATH_MAX);
2374 name_len2++; /* trailing null */
2375 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2376 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2377 name_len2++; /* trailing null */
2378 name_len2++; /* signature byte */
2381 count = 1 /* string type byte */ + name_len + name_len2;
2382 pSMB->hdr.smb_buf_length += count;
2383 pSMB->ByteCount = cpu_to_le16(count);
2385 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2386 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2387 cifs_stats_inc(&tcon->num_hardlinks);
2389 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2391 cifs_buf_release(pSMB);
2393 goto winCreateHardLinkRetry;
2399 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2400 const unsigned char *searchName,
2401 char *symlinkinfo, const int buflen,
2402 const struct nls_table *nls_codepage)
2404 /* SMB_QUERY_FILE_UNIX_LINK */
2405 TRANSACTION2_QPI_REQ *pSMB = NULL;
2406 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2410 __u16 params, byte_count;
2412 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2415 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2420 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2422 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2423 PATH_MAX, nls_codepage);
2424 name_len++; /* trailing null */
2426 } else { /* BB improve the check for buffer overruns BB */
2427 name_len = strnlen(searchName, PATH_MAX);
2428 name_len++; /* trailing null */
2429 strncpy(pSMB->FileName, searchName, name_len);
2432 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2433 pSMB->TotalDataCount = 0;
2434 pSMB->MaxParameterCount = cpu_to_le16(2);
2435 /* BB find exact max data count below from sess structure BB */
2436 pSMB->MaxDataCount = cpu_to_le16(4000);
2437 pSMB->MaxSetupCount = 0;
2441 pSMB->Reserved2 = 0;
2442 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2443 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2444 pSMB->DataCount = 0;
2445 pSMB->DataOffset = 0;
2446 pSMB->SetupCount = 1;
2447 pSMB->Reserved3 = 0;
2448 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2449 byte_count = params + 1 /* pad */ ;
2450 pSMB->TotalParameterCount = cpu_to_le16(params);
2451 pSMB->ParameterCount = pSMB->TotalParameterCount;
2452 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2453 pSMB->Reserved4 = 0;
2454 pSMB->hdr.smb_buf_length += byte_count;
2455 pSMB->ByteCount = cpu_to_le16(byte_count);
2457 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2458 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2460 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2462 /* decode response */
2464 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2465 if (rc || (pSMBr->ByteCount < 2))
2466 /* BB also check enough total bytes returned */
2467 rc = -EIO; /* bad smb */
2469 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2470 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2472 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2473 name_len = UniStrnlen((wchar_t *) ((char *)
2474 &pSMBr->hdr.Protocol + data_offset),
2475 min_t(const int, buflen, count) / 2);
2476 /* BB FIXME investigate remapping reserved chars here */
2477 cifs_strfromUCS_le(symlinkinfo,
2478 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2480 name_len, nls_codepage);
2482 strncpy(symlinkinfo,
2483 (char *) &pSMBr->hdr.Protocol +
2485 min_t(const int, buflen, count));
2487 symlinkinfo[buflen] = 0;
2488 /* just in case so calling code does not go off the end of buffer */
2491 cifs_buf_release(pSMB);
2493 goto querySymLinkRetry;
2497 #ifdef CONFIG_CIFS_EXPERIMENTAL
2498 /* Initialize NT TRANSACT SMB into small smb request buffer.
2499 This assumes that all NT TRANSACTS that we init here have
2500 total parm and data under about 400 bytes (to fit in small cifs
2501 buffer size), which is the case so far, it easily fits. NB:
2502 Setup words themselves and ByteCount
2503 MaxSetupCount (size of returned setup area) and
2504 MaxParameterCount (returned parms size) must be set by caller */
2506 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2507 const int parm_len, struct cifsTconInfo *tcon,
2512 struct smb_com_ntransact_req *pSMB;
2514 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2518 *ret_buf = (void *)pSMB;
2520 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2521 pSMB->TotalDataCount = 0;
2522 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2523 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2524 pSMB->ParameterCount = pSMB->TotalParameterCount;
2525 pSMB->DataCount = pSMB->TotalDataCount;
2526 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2527 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2528 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2529 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2530 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2531 pSMB->SubCommand = cpu_to_le16(sub_command);
2536 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2537 __u32 *pparmlen, __u32 *pdatalen)
2540 __u32 data_count, data_offset, parm_count, parm_offset;
2541 struct smb_com_ntransact_rsp *pSMBr;
2549 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2551 /* ByteCount was converted from little endian in SendReceive */
2552 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2553 (char *)&pSMBr->ByteCount;
2555 data_offset = le32_to_cpu(pSMBr->DataOffset);
2556 data_count = le32_to_cpu(pSMBr->DataCount);
2557 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2558 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2560 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2561 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2563 /* should we also check that parm and data areas do not overlap? */
2564 if (*ppparm > end_of_smb) {
2565 cFYI(1, ("parms start after end of smb"));
2567 } else if (parm_count + *ppparm > end_of_smb) {
2568 cFYI(1, ("parm end after end of smb"));
2570 } else if (*ppdata > end_of_smb) {
2571 cFYI(1, ("data starts after end of smb"));
2573 } else if (data_count + *ppdata > end_of_smb) {
2574 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2575 *ppdata, data_count, (data_count + *ppdata),
2576 end_of_smb, pSMBr));
2578 } else if (parm_count + data_count > pSMBr->ByteCount) {
2579 cFYI(1, ("parm count and data count larger than SMB"));
2582 *pdatalen = data_count;
2583 *pparmlen = parm_count;
2586 #endif /* CIFS_EXPERIMENTAL */
2589 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2590 const unsigned char *searchName,
2591 char *symlinkinfo, const int buflen, __u16 fid,
2592 const struct nls_table *nls_codepage)
2597 struct smb_com_transaction_ioctl_req *pSMB;
2598 struct smb_com_transaction_ioctl_rsp *pSMBr;
2600 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2601 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2606 pSMB->TotalParameterCount = 0 ;
2607 pSMB->TotalDataCount = 0;
2608 pSMB->MaxParameterCount = cpu_to_le32(2);
2609 /* BB find exact data count max from sess structure BB */
2610 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2611 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2612 pSMB->MaxSetupCount = 4;
2614 pSMB->ParameterOffset = 0;
2615 pSMB->DataCount = 0;
2616 pSMB->DataOffset = 0;
2617 pSMB->SetupCount = 4;
2618 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2619 pSMB->ParameterCount = pSMB->TotalParameterCount;
2620 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2621 pSMB->IsFsctl = 1; /* FSCTL */
2622 pSMB->IsRootFlag = 0;
2623 pSMB->Fid = fid; /* file handle always le */
2624 pSMB->ByteCount = 0;
2626 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2627 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2629 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2630 } else { /* decode response */
2631 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2632 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2633 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2634 /* BB also check enough total bytes returned */
2635 rc = -EIO; /* bad smb */
2637 if (data_count && (data_count < 2048)) {
2638 char *end_of_smb = 2 /* sizeof byte count */ +
2640 (char *)&pSMBr->ByteCount;
2642 struct reparse_data *reparse_buf =
2643 (struct reparse_data *)
2644 ((char *)&pSMBr->hdr.Protocol
2646 if ((char *)reparse_buf >= end_of_smb) {
2650 if ((reparse_buf->LinkNamesBuf +
2651 reparse_buf->TargetNameOffset +
2652 reparse_buf->TargetNameLen) >
2654 cFYI(1, ("reparse buf beyond SMB"));
2659 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2660 name_len = UniStrnlen((wchar_t *)
2661 (reparse_buf->LinkNamesBuf +
2662 reparse_buf->TargetNameOffset),
2664 reparse_buf->TargetNameLen / 2));
2665 cifs_strfromUCS_le(symlinkinfo,
2666 (__le16 *) (reparse_buf->LinkNamesBuf +
2667 reparse_buf->TargetNameOffset),
2668 name_len, nls_codepage);
2669 } else { /* ASCII names */
2670 strncpy(symlinkinfo,
2671 reparse_buf->LinkNamesBuf +
2672 reparse_buf->TargetNameOffset,
2673 min_t(const int, buflen,
2674 reparse_buf->TargetNameLen));
2678 cFYI(1, ("Invalid return data count on "
2679 "get reparse info ioctl"));
2681 symlinkinfo[buflen] = 0; /* just in case so the caller
2682 does not go off the end of the buffer */
2683 cFYI(1, ("readlink result - %s", symlinkinfo));
2687 cifs_buf_release(pSMB);
2689 /* Note: On -EAGAIN error only caller can retry on handle based calls
2690 since file handle passed in no longer valid */
2695 #ifdef CONFIG_CIFS_POSIX
2697 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2698 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2699 struct cifs_posix_ace *cifs_ace)
2701 /* u8 cifs fields do not need le conversion */
2702 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2703 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2704 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2705 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2710 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2711 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2712 const int acl_type, const int size_of_data_area)
2717 struct cifs_posix_ace *pACE;
2718 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2719 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2721 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2724 if (acl_type & ACL_TYPE_ACCESS) {
2725 count = le16_to_cpu(cifs_acl->access_entry_count);
2726 pACE = &cifs_acl->ace_array[0];
2727 size = sizeof(struct cifs_posix_acl);
2728 size += sizeof(struct cifs_posix_ace) * count;
2729 /* check if we would go beyond end of SMB */
2730 if (size_of_data_area < size) {
2731 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2732 size_of_data_area, size));
2735 } else if (acl_type & ACL_TYPE_DEFAULT) {
2736 count = le16_to_cpu(cifs_acl->access_entry_count);
2737 size = sizeof(struct cifs_posix_acl);
2738 size += sizeof(struct cifs_posix_ace) * count;
2739 /* skip past access ACEs to get to default ACEs */
2740 pACE = &cifs_acl->ace_array[count];
2741 count = le16_to_cpu(cifs_acl->default_entry_count);
2742 size += sizeof(struct cifs_posix_ace) * count;
2743 /* check if we would go beyond end of SMB */
2744 if (size_of_data_area < size)
2751 size = posix_acl_xattr_size(count);
2752 if ((buflen == 0) || (local_acl == NULL)) {
2753 /* used to query ACL EA size */
2754 } else if (size > buflen) {
2756 } else /* buffer big enough */ {
2757 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2758 for (i = 0; i < count ; i++) {
2759 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2766 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2767 const posix_acl_xattr_entry *local_ace)
2769 __u16 rc = 0; /* 0 = ACL converted ok */
2771 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2772 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2773 /* BB is there a better way to handle the large uid? */
2774 if (local_ace->e_id == cpu_to_le32(-1)) {
2775 /* Probably no need to le convert -1 on any arch but can not hurt */
2776 cifs_ace->cifs_uid = cpu_to_le64(-1);
2778 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2779 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2783 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2784 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2785 const int buflen, const int acl_type)
2788 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2789 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2793 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2796 count = posix_acl_xattr_count((size_t)buflen);
2797 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2799 count, buflen, le32_to_cpu(local_acl->a_version)));
2800 if (le32_to_cpu(local_acl->a_version) != 2) {
2801 cFYI(1, ("unknown POSIX ACL version %d",
2802 le32_to_cpu(local_acl->a_version)));
2805 cifs_acl->version = cpu_to_le16(1);
2806 if (acl_type == ACL_TYPE_ACCESS)
2807 cifs_acl->access_entry_count = cpu_to_le16(count);
2808 else if (acl_type == ACL_TYPE_DEFAULT)
2809 cifs_acl->default_entry_count = cpu_to_le16(count);
2811 cFYI(1, ("unknown ACL type %d", acl_type));
2814 for (i = 0; i < count; i++) {
2815 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2816 &local_acl->a_entries[i]);
2818 /* ACE not converted */
2823 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2824 rc += sizeof(struct cifs_posix_acl);
2825 /* BB add check to make sure ACL does not overflow SMB */
2831 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2832 const unsigned char *searchName,
2833 char *acl_inf, const int buflen, const int acl_type,
2834 const struct nls_table *nls_codepage, int remap)
2836 /* SMB_QUERY_POSIX_ACL */
2837 TRANSACTION2_QPI_REQ *pSMB = NULL;
2838 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2842 __u16 params, byte_count;
2844 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2847 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2852 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2854 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2855 PATH_MAX, nls_codepage, remap);
2856 name_len++; /* trailing null */
2858 pSMB->FileName[name_len] = 0;
2859 pSMB->FileName[name_len+1] = 0;
2860 } else { /* BB improve the check for buffer overruns BB */
2861 name_len = strnlen(searchName, PATH_MAX);
2862 name_len++; /* trailing null */
2863 strncpy(pSMB->FileName, searchName, name_len);
2866 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2867 pSMB->TotalDataCount = 0;
2868 pSMB->MaxParameterCount = cpu_to_le16(2);
2869 /* BB find exact max data count below from sess structure BB */
2870 pSMB->MaxDataCount = cpu_to_le16(4000);
2871 pSMB->MaxSetupCount = 0;
2875 pSMB->Reserved2 = 0;
2876 pSMB->ParameterOffset = cpu_to_le16(
2877 offsetof(struct smb_com_transaction2_qpi_req,
2878 InformationLevel) - 4);
2879 pSMB->DataCount = 0;
2880 pSMB->DataOffset = 0;
2881 pSMB->SetupCount = 1;
2882 pSMB->Reserved3 = 0;
2883 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2884 byte_count = params + 1 /* pad */ ;
2885 pSMB->TotalParameterCount = cpu_to_le16(params);
2886 pSMB->ParameterCount = pSMB->TotalParameterCount;
2887 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2888 pSMB->Reserved4 = 0;
2889 pSMB->hdr.smb_buf_length += byte_count;
2890 pSMB->ByteCount = cpu_to_le16(byte_count);
2892 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2893 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2894 cifs_stats_inc(&tcon->num_acl_get);
2896 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2898 /* decode response */
2900 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2901 if (rc || (pSMBr->ByteCount < 2))
2902 /* BB also check enough total bytes returned */
2903 rc = -EIO; /* bad smb */
2905 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2906 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2907 rc = cifs_copy_posix_acl(acl_inf,
2908 (char *)&pSMBr->hdr.Protocol+data_offset,
2909 buflen, acl_type, count);
2912 cifs_buf_release(pSMB);
2919 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2920 const unsigned char *fileName,
2921 const char *local_acl, const int buflen,
2923 const struct nls_table *nls_codepage, int remap)
2925 struct smb_com_transaction2_spi_req *pSMB = NULL;
2926 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2930 int bytes_returned = 0;
2931 __u16 params, byte_count, data_count, param_offset, offset;
2933 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2935 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2939 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2941 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2942 PATH_MAX, nls_codepage, remap);
2943 name_len++; /* trailing null */
2945 } else { /* BB improve the check for buffer overruns BB */
2946 name_len = strnlen(fileName, PATH_MAX);
2947 name_len++; /* trailing null */
2948 strncpy(pSMB->FileName, fileName, name_len);
2950 params = 6 + name_len;
2951 pSMB->MaxParameterCount = cpu_to_le16(2);
2952 /* BB find max SMB size from sess */
2953 pSMB->MaxDataCount = cpu_to_le16(1000);
2954 pSMB->MaxSetupCount = 0;
2958 pSMB->Reserved2 = 0;
2959 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2960 InformationLevel) - 4;
2961 offset = param_offset + params;
2962 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2963 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2965 /* convert to on the wire format for POSIX ACL */
2966 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2968 if (data_count == 0) {
2970 goto setACLerrorExit;
2972 pSMB->DataOffset = cpu_to_le16(offset);
2973 pSMB->SetupCount = 1;
2974 pSMB->Reserved3 = 0;
2975 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2976 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2977 byte_count = 3 /* pad */ + params + data_count;
2978 pSMB->DataCount = cpu_to_le16(data_count);
2979 pSMB->TotalDataCount = pSMB->DataCount;
2980 pSMB->ParameterCount = cpu_to_le16(params);
2981 pSMB->TotalParameterCount = pSMB->ParameterCount;
2982 pSMB->Reserved4 = 0;
2983 pSMB->hdr.smb_buf_length += byte_count;
2984 pSMB->ByteCount = cpu_to_le16(byte_count);
2985 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2986 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2988 cFYI(1, ("Set POSIX ACL returned %d", rc));
2991 cifs_buf_release(pSMB);
2997 /* BB fix tabs in this function FIXME BB */
2999 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3000 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3003 struct smb_t2_qfi_req *pSMB = NULL;
3004 struct smb_t2_qfi_rsp *pSMBr = NULL;
3006 __u16 params, byte_count;
3008 cFYI(1, ("In GetExtAttr"));
3013 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3018 params = 2 /* level */ + 2 /* fid */;
3019 pSMB->t2.TotalDataCount = 0;
3020 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3021 /* BB find exact max data count below from sess structure BB */
3022 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3023 pSMB->t2.MaxSetupCount = 0;
3024 pSMB->t2.Reserved = 0;
3026 pSMB->t2.Timeout = 0;
3027 pSMB->t2.Reserved2 = 0;
3028 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3030 pSMB->t2.DataCount = 0;
3031 pSMB->t2.DataOffset = 0;
3032 pSMB->t2.SetupCount = 1;
3033 pSMB->t2.Reserved3 = 0;
3034 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3035 byte_count = params + 1 /* pad */ ;
3036 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3037 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3038 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3041 pSMB->hdr.smb_buf_length += byte_count;
3042 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3044 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3045 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3047 cFYI(1, ("error %d in GetExtAttr", rc));
3049 /* decode response */
3050 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3051 if (rc || (pSMBr->ByteCount < 2))
3052 /* BB also check enough total bytes returned */
3053 /* If rc should we check for EOPNOSUPP and
3054 disable the srvino flag? or in caller? */
3055 rc = -EIO; /* bad smb */
3057 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3058 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3059 struct file_chattr_info *pfinfo;
3060 /* BB Do we need a cast or hash here ? */
3062 cFYI(1, ("Illegal size ret in GetExtAttr"));
3066 pfinfo = (struct file_chattr_info *)
3067 (data_offset + (char *) &pSMBr->hdr.Protocol);
3068 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3069 *pMask = le64_to_cpu(pfinfo->mask);
3073 cifs_buf_release(pSMB);
3075 goto GetExtAttrRetry;
3079 #endif /* CONFIG_POSIX */
3081 #ifdef CONFIG_CIFS_EXPERIMENTAL
3082 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3084 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3085 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3089 QUERY_SEC_DESC_REQ *pSMB;
3092 cFYI(1, ("GetCifsACL"));
3097 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3098 8 /* parm len */, tcon, (void **) &pSMB);
3102 pSMB->MaxParameterCount = cpu_to_le32(4);
3103 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3104 pSMB->MaxSetupCount = 0;
3105 pSMB->Fid = fid; /* file handle always le */
3106 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3108 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3109 pSMB->hdr.smb_buf_length += 11;
3110 iov[0].iov_base = (char *)pSMB;
3111 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3113 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3115 cifs_stats_inc(&tcon->num_acl_get);
3117 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3118 } else { /* decode response */
3122 struct smb_com_ntransact_rsp *pSMBr;
3125 /* validate_nttransact */
3126 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3127 &pdata, &parm_len, pbuflen);
3130 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3132 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3134 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3135 rc = -EIO; /* bad smb */
3140 /* BB check that data area is minimum length and as big as acl_len */
3142 acl_len = le32_to_cpu(*parm);
3143 if (acl_len != *pbuflen) {
3144 cERROR(1, ("acl length %d does not match %d",
3145 acl_len, *pbuflen));
3146 if (*pbuflen > acl_len)
3150 /* check if buffer is big enough for the acl
3151 header followed by the smallest SID */
3152 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3153 (*pbuflen >= 64 * 1024)) {
3154 cERROR(1, ("bad acl length %d", *pbuflen));
3158 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3159 if (*acl_inf == NULL) {
3163 memcpy(*acl_inf, pdata, *pbuflen);
3167 if (buf_type == CIFS_SMALL_BUFFER)
3168 cifs_small_buf_release(iov[0].iov_base);
3169 else if (buf_type == CIFS_LARGE_BUFFER)
3170 cifs_buf_release(iov[0].iov_base);
3171 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3176 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3177 struct cifs_ntsd *pntsd, __u32 acllen)
3179 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3181 int bytes_returned = 0;
3182 SET_SEC_DESC_REQ *pSMB = NULL;
3183 NTRANSACT_RSP *pSMBr = NULL;
3186 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3191 pSMB->MaxSetupCount = 0;
3195 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3196 data_count = acllen;
3197 data_offset = param_offset + param_count;
3198 byte_count = 3 /* pad */ + param_count;
3200 pSMB->DataCount = cpu_to_le32(data_count);
3201 pSMB->TotalDataCount = pSMB->DataCount;
3202 pSMB->MaxParameterCount = cpu_to_le32(4);
3203 pSMB->MaxDataCount = cpu_to_le32(16384);
3204 pSMB->ParameterCount = cpu_to_le32(param_count);
3205 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3206 pSMB->TotalParameterCount = pSMB->ParameterCount;
3207 pSMB->DataOffset = cpu_to_le32(data_offset);
3208 pSMB->SetupCount = 0;
3209 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3210 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3212 pSMB->Fid = fid; /* file handle always le */
3213 pSMB->Reserved2 = 0;
3214 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3216 if (pntsd && acllen) {
3217 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3220 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3223 pSMB->hdr.smb_buf_length += byte_count;
3225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3228 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3230 cFYI(1, ("Set CIFS ACL returned %d", rc));
3231 cifs_buf_release(pSMB);
3234 goto setCifsAclRetry;
3239 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3241 /* Legacy Query Path Information call for lookup to old servers such
3243 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3244 const unsigned char *searchName,
3245 FILE_ALL_INFO *pFinfo,
3246 const struct nls_table *nls_codepage, int remap)
3248 QUERY_INFORMATION_REQ *pSMB;
3249 QUERY_INFORMATION_RSP *pSMBr;
3254 cFYI(1, ("In SMBQPath path %s", searchName));
3256 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3261 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3263 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3264 PATH_MAX, nls_codepage, remap);
3265 name_len++; /* trailing null */
3268 name_len = strnlen(searchName, PATH_MAX);
3269 name_len++; /* trailing null */
3270 strncpy(pSMB->FileName, searchName, name_len);
3272 pSMB->BufferFormat = 0x04;
3273 name_len++; /* account for buffer type byte */
3274 pSMB->hdr.smb_buf_length += (__u16) name_len;
3275 pSMB->ByteCount = cpu_to_le16(name_len);
3277 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3278 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3280 cFYI(1, ("Send error in QueryInfo = %d", rc));
3281 } else if (pFinfo) {
3283 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3285 /* decode response */
3286 /* BB FIXME - add time zone adjustment BB */
3287 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3290 /* decode time fields */
3291 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3292 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3293 pFinfo->LastAccessTime = 0;
3294 pFinfo->AllocationSize =
3295 cpu_to_le64(le32_to_cpu(pSMBr->size));
3296 pFinfo->EndOfFile = pFinfo->AllocationSize;
3297 pFinfo->Attributes =
3298 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3300 rc = -EIO; /* bad buffer passed in */
3302 cifs_buf_release(pSMB);
3314 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3315 const unsigned char *searchName,
3316 FILE_ALL_INFO *pFindData,
3317 int legacy /* old style infolevel */,
3318 const struct nls_table *nls_codepage, int remap)
3320 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3321 TRANSACTION2_QPI_REQ *pSMB = NULL;
3322 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3326 __u16 params, byte_count;
3328 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3330 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3335 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3337 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3338 PATH_MAX, nls_codepage, remap);
3339 name_len++; /* trailing null */
3341 } else { /* BB improve the check for buffer overruns BB */
3342 name_len = strnlen(searchName, PATH_MAX);
3343 name_len++; /* trailing null */
3344 strncpy(pSMB->FileName, searchName, name_len);
3347 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3348 pSMB->TotalDataCount = 0;
3349 pSMB->MaxParameterCount = cpu_to_le16(2);
3350 /* BB find exact max SMB PDU from sess structure BB */
3351 pSMB->MaxDataCount = cpu_to_le16(4000);
3352 pSMB->MaxSetupCount = 0;
3356 pSMB->Reserved2 = 0;
3357 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3358 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3359 pSMB->DataCount = 0;
3360 pSMB->DataOffset = 0;
3361 pSMB->SetupCount = 1;
3362 pSMB->Reserved3 = 0;
3363 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3364 byte_count = params + 1 /* pad */ ;
3365 pSMB->TotalParameterCount = cpu_to_le16(params);
3366 pSMB->ParameterCount = pSMB->TotalParameterCount;
3368 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3370 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3371 pSMB->Reserved4 = 0;
3372 pSMB->hdr.smb_buf_length += byte_count;
3373 pSMB->ByteCount = cpu_to_le16(byte_count);
3375 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3376 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3378 cFYI(1, ("Send error in QPathInfo = %d", rc));
3379 } else { /* decode response */
3380 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3382 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3384 else if (!legacy && (pSMBr->ByteCount < 40))
3385 rc = -EIO; /* bad smb */
3386 else if (legacy && (pSMBr->ByteCount < 24))
3387 rc = -EIO; /* 24 or 26 expected but we do not read
3389 else if (pFindData) {
3391 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3393 /* On legacy responses we do not read the last field,
3394 EAsize, fortunately since it varies by subdialect and
3395 also note it differs on Set vs. Get, ie two bytes or 4
3396 bytes depending but we don't care here */
3398 size = sizeof(FILE_INFO_STANDARD);
3400 size = sizeof(FILE_ALL_INFO);
3401 memcpy((char *) pFindData,
3402 (char *) &pSMBr->hdr.Protocol +
3407 cifs_buf_release(pSMB);
3409 goto QPathInfoRetry;
3415 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3416 const unsigned char *searchName,
3417 FILE_UNIX_BASIC_INFO *pFindData,
3418 const struct nls_table *nls_codepage, int remap)
3420 /* SMB_QUERY_FILE_UNIX_BASIC */
3421 TRANSACTION2_QPI_REQ *pSMB = NULL;
3422 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3424 int bytes_returned = 0;
3426 __u16 params, byte_count;
3428 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3430 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3435 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3437 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3438 PATH_MAX, nls_codepage, remap);
3439 name_len++; /* trailing null */
3441 } else { /* BB improve the check for buffer overruns BB */
3442 name_len = strnlen(searchName, PATH_MAX);
3443 name_len++; /* trailing null */
3444 strncpy(pSMB->FileName, searchName, name_len);
3447 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3448 pSMB->TotalDataCount = 0;
3449 pSMB->MaxParameterCount = cpu_to_le16(2);
3450 /* BB find exact max SMB PDU from sess structure BB */
3451 pSMB->MaxDataCount = cpu_to_le16(4000);
3452 pSMB->MaxSetupCount = 0;
3456 pSMB->Reserved2 = 0;
3457 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3458 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3459 pSMB->DataCount = 0;
3460 pSMB->DataOffset = 0;
3461 pSMB->SetupCount = 1;
3462 pSMB->Reserved3 = 0;
3463 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3464 byte_count = params + 1 /* pad */ ;
3465 pSMB->TotalParameterCount = cpu_to_le16(params);
3466 pSMB->ParameterCount = pSMB->TotalParameterCount;
3467 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3468 pSMB->Reserved4 = 0;
3469 pSMB->hdr.smb_buf_length += byte_count;
3470 pSMB->ByteCount = cpu_to_le16(byte_count);
3472 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3473 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3475 cFYI(1, ("Send error in QPathInfo = %d", rc));
3476 } else { /* decode response */
3477 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3479 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3480 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3481 "Unix Extensions can be disabled on mount "
3482 "by specifying the nosfu mount option."));
3483 rc = -EIO; /* bad smb */
3485 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3486 memcpy((char *) pFindData,
3487 (char *) &pSMBr->hdr.Protocol +
3489 sizeof(FILE_UNIX_BASIC_INFO));
3492 cifs_buf_release(pSMB);
3494 goto UnixQPathInfoRetry;
3499 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3501 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3502 const char *searchName,
3503 const struct nls_table *nls_codepage,
3505 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3507 /* level 257 SMB_ */
3508 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3509 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3510 T2_FFIRST_RSP_PARMS *parms;
3512 int bytes_returned = 0;
3514 __u16 params, byte_count;
3516 cFYI(1, ("In FindFirst for %s", searchName));
3519 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3524 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3526 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3527 PATH_MAX, nls_codepage, remap);
3528 /* We can not add the asterik earlier in case
3529 it got remapped to 0xF03A as if it were part of the
3530 directory name instead of a wildcard */
3532 pSMB->FileName[name_len] = dirsep;
3533 pSMB->FileName[name_len+1] = 0;
3534 pSMB->FileName[name_len+2] = '*';
3535 pSMB->FileName[name_len+3] = 0;
3536 name_len += 4; /* now the trailing null */
3537 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3538 pSMB->FileName[name_len+1] = 0;
3540 } else { /* BB add check for overrun of SMB buf BB */
3541 name_len = strnlen(searchName, PATH_MAX);
3542 /* BB fix here and in unicode clause above ie
3543 if (name_len > buffersize-header)
3544 free buffer exit; BB */
3545 strncpy(pSMB->FileName, searchName, name_len);
3546 pSMB->FileName[name_len] = dirsep;
3547 pSMB->FileName[name_len+1] = '*';
3548 pSMB->FileName[name_len+2] = 0;
3552 params = 12 + name_len /* includes null */ ;
3553 pSMB->TotalDataCount = 0; /* no EAs */
3554 pSMB->MaxParameterCount = cpu_to_le16(10);
3555 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3556 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3557 pSMB->MaxSetupCount = 0;
3561 pSMB->Reserved2 = 0;
3562 byte_count = params + 1 /* pad */ ;
3563 pSMB->TotalParameterCount = cpu_to_le16(params);
3564 pSMB->ParameterCount = pSMB->TotalParameterCount;
3565 pSMB->ParameterOffset = cpu_to_le16(
3566 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3568 pSMB->DataCount = 0;
3569 pSMB->DataOffset = 0;
3570 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3571 pSMB->Reserved3 = 0;
3572 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3573 pSMB->SearchAttributes =
3574 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3576 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3577 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3578 CIFS_SEARCH_RETURN_RESUME);
3579 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3581 /* BB what should we set StorageType to? Does it matter? BB */
3582 pSMB->SearchStorageType = 0;
3583 pSMB->hdr.smb_buf_length += byte_count;
3584 pSMB->ByteCount = cpu_to_le16(byte_count);
3586 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3587 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3588 cifs_stats_inc(&tcon->num_ffirst);
3590 if (rc) {/* BB add logic to retry regular search if Unix search
3591 rejected unexpectedly by server */
3592 /* BB Add code to handle unsupported level rc */
3593 cFYI(1, ("Error in FindFirst = %d", rc));
3595 cifs_buf_release(pSMB);
3597 /* BB eventually could optimize out free and realloc of buf */
3600 goto findFirstRetry;
3601 } else { /* decode response */
3602 /* BB remember to free buffer if error BB */
3603 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3607 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3608 psrch_inf->unicode = true;
3610 psrch_inf->unicode = false;
3612 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3613 psrch_inf->smallBuf = 0;
3614 psrch_inf->srch_entries_start =
3615 (char *) &pSMBr->hdr.Protocol +
3616 le16_to_cpu(pSMBr->t2.DataOffset);
3617 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3618 le16_to_cpu(pSMBr->t2.ParameterOffset));
3620 if (parms->EndofSearch)
3621 psrch_inf->endOfSearch = true;
3623 psrch_inf->endOfSearch = false;
3625 psrch_inf->entries_in_buffer =
3626 le16_to_cpu(parms->SearchCount);
3627 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3628 psrch_inf->entries_in_buffer;
3629 lnoff = le16_to_cpu(parms->LastNameOffset);
3630 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3632 cERROR(1, ("ignoring corrupt resume name"));
3633 psrch_inf->last_entry = NULL;
3637 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3640 *pnetfid = parms->SearchHandle;
3642 cifs_buf_release(pSMB);
3649 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3650 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3652 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3653 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3654 T2_FNEXT_RSP_PARMS *parms;
3655 char *response_data;
3657 int bytes_returned, name_len;
3658 __u16 params, byte_count;
3660 cFYI(1, ("In FindNext"));
3662 if (psrch_inf->endOfSearch)
3665 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3670 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3672 pSMB->TotalDataCount = 0; /* no EAs */
3673 pSMB->MaxParameterCount = cpu_to_le16(8);
3674 pSMB->MaxDataCount =
3675 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3677 pSMB->MaxSetupCount = 0;
3681 pSMB->Reserved2 = 0;
3682 pSMB->ParameterOffset = cpu_to_le16(
3683 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3684 pSMB->DataCount = 0;
3685 pSMB->DataOffset = 0;
3686 pSMB->SetupCount = 1;
3687 pSMB->Reserved3 = 0;
3688 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3689 pSMB->SearchHandle = searchHandle; /* always kept as le */
3691 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3692 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3693 pSMB->ResumeKey = psrch_inf->resume_key;
3695 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3697 name_len = psrch_inf->resume_name_len;
3699 if (name_len < PATH_MAX) {
3700 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3701 byte_count += name_len;
3702 /* 14 byte parm len above enough for 2 byte null terminator */
3703 pSMB->ResumeFileName[name_len] = 0;
3704 pSMB->ResumeFileName[name_len+1] = 0;
3707 goto FNext2_err_exit;
3709 byte_count = params + 1 /* pad */ ;
3710 pSMB->TotalParameterCount = cpu_to_le16(params);
3711 pSMB->ParameterCount = pSMB->TotalParameterCount;
3712 pSMB->hdr.smb_buf_length += byte_count;
3713 pSMB->ByteCount = cpu_to_le16(byte_count);
3715 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3716 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3717 cifs_stats_inc(&tcon->num_fnext);
3720 psrch_inf->endOfSearch = true;
3721 cifs_buf_release(pSMB);
3722 rc = 0; /* search probably was closed at end of search*/
3724 cFYI(1, ("FindNext returned = %d", rc));
3725 } else { /* decode response */
3726 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3731 /* BB fixme add lock for file (srch_info) struct here */
3732 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3733 psrch_inf->unicode = true;
3735 psrch_inf->unicode = false;
3736 response_data = (char *) &pSMBr->hdr.Protocol +
3737 le16_to_cpu(pSMBr->t2.ParameterOffset);
3738 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3739 response_data = (char *)&pSMBr->hdr.Protocol +
3740 le16_to_cpu(pSMBr->t2.DataOffset);
3741 if (psrch_inf->smallBuf)
3742 cifs_small_buf_release(
3743 psrch_inf->ntwrk_buf_start);
3745 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3746 psrch_inf->srch_entries_start = response_data;
3747 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3748 psrch_inf->smallBuf = 0;
3749 if (parms->EndofSearch)
3750 psrch_inf->endOfSearch = true;
3752 psrch_inf->endOfSearch = false;
3753 psrch_inf->entries_in_buffer =
3754 le16_to_cpu(parms->SearchCount);
3755 psrch_inf->index_of_last_entry +=
3756 psrch_inf->entries_in_buffer;
3757 lnoff = le16_to_cpu(parms->LastNameOffset);
3758 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3760 cERROR(1, ("ignoring corrupt resume name"));
3761 psrch_inf->last_entry = NULL;
3764 psrch_inf->last_entry =
3765 psrch_inf->srch_entries_start + lnoff;
3767 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3768 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3770 /* BB fixme add unlock here */
3775 /* BB On error, should we leave previous search buf (and count and
3776 last entry fields) intact or free the previous one? */
3778 /* Note: On -EAGAIN error only caller can retry on handle based calls
3779 since file handle passed in no longer valid */
3782 cifs_buf_release(pSMB);
3787 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3788 const __u16 searchHandle)
3791 FINDCLOSE_REQ *pSMB = NULL;
3793 cFYI(1, ("In CIFSSMBFindClose"));
3794 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3796 /* no sense returning error if session restarted
3797 as file handle has been closed */
3803 pSMB->FileID = searchHandle;
3804 pSMB->ByteCount = 0;
3805 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3807 cERROR(1, ("Send error in FindClose = %d", rc));
3809 cifs_stats_inc(&tcon->num_fclose);
3811 /* Since session is dead, search handle closed on server already */
3819 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3820 const unsigned char *searchName,
3821 __u64 *inode_number,
3822 const struct nls_table *nls_codepage, int remap)
3825 TRANSACTION2_QPI_REQ *pSMB = NULL;
3826 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3827 int name_len, bytes_returned;
3828 __u16 params, byte_count;
3830 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3834 GetInodeNumberRetry:
3835 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3842 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3843 PATH_MAX, nls_codepage, remap);
3844 name_len++; /* trailing null */
3846 } else { /* BB improve the check for buffer overruns BB */
3847 name_len = strnlen(searchName, PATH_MAX);
3848 name_len++; /* trailing null */
3849 strncpy(pSMB->FileName, searchName, name_len);
3852 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3853 pSMB->TotalDataCount = 0;
3854 pSMB->MaxParameterCount = cpu_to_le16(2);
3855 /* BB find exact max data count below from sess structure BB */
3856 pSMB->MaxDataCount = cpu_to_le16(4000);
3857 pSMB->MaxSetupCount = 0;
3861 pSMB->Reserved2 = 0;
3862 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3863 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3864 pSMB->DataCount = 0;
3865 pSMB->DataOffset = 0;
3866 pSMB->SetupCount = 1;
3867 pSMB->Reserved3 = 0;
3868 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3869 byte_count = params + 1 /* pad */ ;
3870 pSMB->TotalParameterCount = cpu_to_le16(params);
3871 pSMB->ParameterCount = pSMB->TotalParameterCount;
3872 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3873 pSMB->Reserved4 = 0;
3874 pSMB->hdr.smb_buf_length += byte_count;
3875 pSMB->ByteCount = cpu_to_le16(byte_count);
3877 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3878 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3880 cFYI(1, ("error %d in QueryInternalInfo", rc));
3882 /* decode response */
3883 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3884 if (rc || (pSMBr->ByteCount < 2))
3885 /* BB also check enough total bytes returned */
3886 /* If rc should we check for EOPNOSUPP and
3887 disable the srvino flag? or in caller? */
3888 rc = -EIO; /* bad smb */
3890 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3891 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3892 struct file_internal_info *pfinfo;
3893 /* BB Do we need a cast or hash here ? */
3895 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3897 goto GetInodeNumOut;
3899 pfinfo = (struct file_internal_info *)
3900 (data_offset + (char *) &pSMBr->hdr.Protocol);
3901 *inode_number = pfinfo->UniqueId;
3905 cifs_buf_release(pSMB);
3907 goto GetInodeNumberRetry;
3911 /* computes length of UCS string converted to host codepage
3913 * @maxlen: length of the input string in UCS characters
3916 * return: size of input string in host codepage
3918 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3919 const struct nls_table *nls_codepage) {
3924 for (i = 0; (i < maxlen) && src[i]; ++i) {
3925 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3926 to, NLS_MAX_CHARSET_SIZE);
3927 hostlen += charlen > 0 ? charlen : 1;
3932 /* parses DFS refferal V3 structure
3933 * caller is responsible for freeing target_nodes
3936 * on failure - errno
3939 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3940 unsigned int *num_of_nodes,
3941 struct dfs_info3_param **target_nodes,
3942 const struct nls_table *nls_codepage, int remap,
3943 const char *searchName)
3948 struct dfs_referral_level_3 *ref;
3950 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3954 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3956 if (*num_of_nodes < 1) {
3957 cERROR(1, ("num_referrals: must be at least > 0,"
3958 "but we get num_referrals = %d\n", *num_of_nodes));
3960 goto parse_DFS_referrals_exit;
3963 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3964 if (ref->VersionNumber != cpu_to_le16(3)) {
3965 cERROR(1, ("Referrals of V%d version are not supported,"
3966 "should be V3", le16_to_cpu(ref->VersionNumber)));
3968 goto parse_DFS_referrals_exit;
3971 /* get the upper boundary of the resp buffer */
3972 data_end = (char *)(&(pSMBr->PathConsumed)) +
3973 le16_to_cpu(pSMBr->t2.DataCount);
3975 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3977 le16_to_cpu(pSMBr->DFSFlags)));
3979 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3980 *num_of_nodes, GFP_KERNEL);
3981 if (*target_nodes == NULL) {
3982 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3984 goto parse_DFS_referrals_exit;
3987 /* collect neccessary data from referrals */
3988 for (i = 0; i < *num_of_nodes; i++) {
3991 struct dfs_info3_param *node = (*target_nodes)+i;
3993 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3995 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3997 cifsConvertToUCS((__le16 *) tmp, searchName,
3998 PATH_MAX, nls_codepage, remap);
3999 node->path_consumed = hostlen_fromUCS(tmp,
4000 le16_to_cpu(pSMBr->PathConsumed)/2,
4004 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4006 node->server_type = le16_to_cpu(ref->ServerType);
4007 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4010 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4011 max_len = data_end - temp;
4012 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4013 max_len, is_unicode, nls_codepage);
4015 goto parse_DFS_referrals_exit;
4017 /* copy link target UNC */
4018 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4019 max_len = data_end - temp;
4020 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4021 max_len, is_unicode, nls_codepage);
4023 goto parse_DFS_referrals_exit;
4025 ref += le16_to_cpu(ref->Size);
4028 parse_DFS_referrals_exit:
4030 free_dfs_info_array(*target_nodes, *num_of_nodes);
4031 *target_nodes = NULL;
4038 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4039 const unsigned char *searchName,
4040 struct dfs_info3_param **target_nodes,
4041 unsigned int *num_of_nodes,
4042 const struct nls_table *nls_codepage, int remap)
4044 /* TRANS2_GET_DFS_REFERRAL */
4045 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4046 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4050 __u16 params, byte_count;
4052 *target_nodes = NULL;
4054 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4058 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4063 /* server pointer checked in called function,
4064 but should never be null here anyway */
4065 pSMB->hdr.Mid = GetNextMid(ses->server);
4066 pSMB->hdr.Tid = ses->ipc_tid;
4067 pSMB->hdr.Uid = ses->Suid;
4068 if (ses->capabilities & CAP_STATUS32)
4069 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4070 if (ses->capabilities & CAP_DFS)
4071 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4073 if (ses->capabilities & CAP_UNICODE) {
4074 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4076 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4077 searchName, PATH_MAX, nls_codepage, remap);
4078 name_len++; /* trailing null */
4080 } else { /* BB improve the check for buffer overruns BB */
4081 name_len = strnlen(searchName, PATH_MAX);
4082 name_len++; /* trailing null */
4083 strncpy(pSMB->RequestFileName, searchName, name_len);
4087 if (ses->server->secMode &
4088 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4089 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4092 pSMB->hdr.Uid = ses->Suid;
4094 params = 2 /* level */ + name_len /*includes null */ ;
4095 pSMB->TotalDataCount = 0;
4096 pSMB->DataCount = 0;
4097 pSMB->DataOffset = 0;
4098 pSMB->MaxParameterCount = 0;
4099 /* BB find exact max SMB PDU from sess structure BB */
4100 pSMB->MaxDataCount = cpu_to_le16(4000);
4101 pSMB->MaxSetupCount = 0;
4105 pSMB->Reserved2 = 0;
4106 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4107 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4108 pSMB->SetupCount = 1;
4109 pSMB->Reserved3 = 0;
4110 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4111 byte_count = params + 3 /* pad */ ;
4112 pSMB->ParameterCount = cpu_to_le16(params);
4113 pSMB->TotalParameterCount = pSMB->ParameterCount;
4114 pSMB->MaxReferralLevel = cpu_to_le16(3);
4115 pSMB->hdr.smb_buf_length += byte_count;
4116 pSMB->ByteCount = cpu_to_le16(byte_count);
4118 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4119 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4121 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4124 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4126 /* BB Also check if enough total bytes returned? */
4127 if (rc || (pSMBr->ByteCount < 17)) {
4128 rc = -EIO; /* bad smb */
4132 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4134 le16_to_cpu(pSMBr->t2.DataOffset)));
4136 /* parse returned result into more usable form */
4137 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4138 target_nodes, nls_codepage, remap,
4142 cifs_buf_release(pSMB);
4150 /* Query File System Info such as free space to old servers such as Win 9x */
4152 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4154 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4155 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4156 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4157 FILE_SYSTEM_ALLOC_INFO *response_data;
4159 int bytes_returned = 0;
4160 __u16 params, byte_count;
4162 cFYI(1, ("OldQFSInfo"));
4164 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4169 params = 2; /* level */
4170 pSMB->TotalDataCount = 0;
4171 pSMB->MaxParameterCount = cpu_to_le16(2);
4172 pSMB->MaxDataCount = cpu_to_le16(1000);
4173 pSMB->MaxSetupCount = 0;
4177 pSMB->Reserved2 = 0;
4178 byte_count = params + 1 /* pad */ ;
4179 pSMB->TotalParameterCount = cpu_to_le16(params);
4180 pSMB->ParameterCount = pSMB->TotalParameterCount;
4181 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4182 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4183 pSMB->DataCount = 0;
4184 pSMB->DataOffset = 0;
4185 pSMB->SetupCount = 1;
4186 pSMB->Reserved3 = 0;
4187 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4188 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4189 pSMB->hdr.smb_buf_length += byte_count;
4190 pSMB->ByteCount = cpu_to_le16(byte_count);
4192 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4193 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4195 cFYI(1, ("Send error in QFSInfo = %d", rc));
4196 } else { /* decode response */
4197 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4199 if (rc || (pSMBr->ByteCount < 18))
4200 rc = -EIO; /* bad smb */
4202 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4203 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4204 pSMBr->ByteCount, data_offset));
4206 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4207 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4209 le16_to_cpu(response_data->BytesPerSector) *
4210 le32_to_cpu(response_data->
4211 SectorsPerAllocationUnit);
4213 le32_to_cpu(response_data->TotalAllocationUnits);
4214 FSData->f_bfree = FSData->f_bavail =
4215 le32_to_cpu(response_data->FreeAllocationUnits);
4217 ("Blocks: %lld Free: %lld Block size %ld",
4218 (unsigned long long)FSData->f_blocks,
4219 (unsigned long long)FSData->f_bfree,
4223 cifs_buf_release(pSMB);
4226 goto oldQFSInfoRetry;
4232 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4234 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4235 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4236 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4237 FILE_SYSTEM_INFO *response_data;
4239 int bytes_returned = 0;
4240 __u16 params, byte_count;
4242 cFYI(1, ("In QFSInfo"));
4244 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4249 params = 2; /* level */
4250 pSMB->TotalDataCount = 0;
4251 pSMB->MaxParameterCount = cpu_to_le16(2);
4252 pSMB->MaxDataCount = cpu_to_le16(1000);
4253 pSMB->MaxSetupCount = 0;
4257 pSMB->Reserved2 = 0;
4258 byte_count = params + 1 /* pad */ ;
4259 pSMB->TotalParameterCount = cpu_to_le16(params);
4260 pSMB->ParameterCount = pSMB->TotalParameterCount;
4261 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4262 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4263 pSMB->DataCount = 0;
4264 pSMB->DataOffset = 0;
4265 pSMB->SetupCount = 1;
4266 pSMB->Reserved3 = 0;
4267 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4268 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4269 pSMB->hdr.smb_buf_length += byte_count;
4270 pSMB->ByteCount = cpu_to_le16(byte_count);
4272 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4273 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4275 cFYI(1, ("Send error in QFSInfo = %d", rc));
4276 } else { /* decode response */
4277 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4279 if (rc || (pSMBr->ByteCount < 24))
4280 rc = -EIO; /* bad smb */
4282 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4286 *) (((char *) &pSMBr->hdr.Protocol) +
4289 le32_to_cpu(response_data->BytesPerSector) *
4290 le32_to_cpu(response_data->
4291 SectorsPerAllocationUnit);
4293 le64_to_cpu(response_data->TotalAllocationUnits);
4294 FSData->f_bfree = FSData->f_bavail =
4295 le64_to_cpu(response_data->FreeAllocationUnits);
4297 ("Blocks: %lld Free: %lld Block size %ld",
4298 (unsigned long long)FSData->f_blocks,
4299 (unsigned long long)FSData->f_bfree,
4303 cifs_buf_release(pSMB);
4312 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4314 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4315 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4316 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4317 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4319 int bytes_returned = 0;
4320 __u16 params, byte_count;
4322 cFYI(1, ("In QFSAttributeInfo"));
4324 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4329 params = 2; /* level */
4330 pSMB->TotalDataCount = 0;
4331 pSMB->MaxParameterCount = cpu_to_le16(2);
4332 /* BB find exact max SMB PDU from sess structure BB */
4333 pSMB->MaxDataCount = cpu_to_le16(1000);
4334 pSMB->MaxSetupCount = 0;
4338 pSMB->Reserved2 = 0;
4339 byte_count = params + 1 /* pad */ ;
4340 pSMB->TotalParameterCount = cpu_to_le16(params);
4341 pSMB->ParameterCount = pSMB->TotalParameterCount;
4342 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4343 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4344 pSMB->DataCount = 0;
4345 pSMB->DataOffset = 0;
4346 pSMB->SetupCount = 1;
4347 pSMB->Reserved3 = 0;
4348 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4349 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4350 pSMB->hdr.smb_buf_length += byte_count;
4351 pSMB->ByteCount = cpu_to_le16(byte_count);
4353 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4354 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4356 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4357 } else { /* decode response */
4358 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4360 if (rc || (pSMBr->ByteCount < 13)) {
4361 /* BB also check if enough bytes returned */
4362 rc = -EIO; /* bad smb */
4364 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4366 (FILE_SYSTEM_ATTRIBUTE_INFO
4367 *) (((char *) &pSMBr->hdr.Protocol) +
4369 memcpy(&tcon->fsAttrInfo, response_data,
4370 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4373 cifs_buf_release(pSMB);
4376 goto QFSAttributeRetry;
4382 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4384 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4385 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4386 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4387 FILE_SYSTEM_DEVICE_INFO *response_data;
4389 int bytes_returned = 0;
4390 __u16 params, byte_count;
4392 cFYI(1, ("In QFSDeviceInfo"));
4394 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4399 params = 2; /* level */
4400 pSMB->TotalDataCount = 0;
4401 pSMB->MaxParameterCount = cpu_to_le16(2);
4402 /* BB find exact max SMB PDU from sess structure BB */
4403 pSMB->MaxDataCount = cpu_to_le16(1000);
4404 pSMB->MaxSetupCount = 0;
4408 pSMB->Reserved2 = 0;
4409 byte_count = params + 1 /* pad */ ;
4410 pSMB->TotalParameterCount = cpu_to_le16(params);
4411 pSMB->ParameterCount = pSMB->TotalParameterCount;
4412 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4413 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4415 pSMB->DataCount = 0;
4416 pSMB->DataOffset = 0;
4417 pSMB->SetupCount = 1;
4418 pSMB->Reserved3 = 0;
4419 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4420 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4421 pSMB->hdr.smb_buf_length += byte_count;
4422 pSMB->ByteCount = cpu_to_le16(byte_count);
4424 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4425 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4427 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4428 } else { /* decode response */
4429 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4431 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4432 rc = -EIO; /* bad smb */
4434 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4436 (FILE_SYSTEM_DEVICE_INFO *)
4437 (((char *) &pSMBr->hdr.Protocol) +
4439 memcpy(&tcon->fsDevInfo, response_data,
4440 sizeof(FILE_SYSTEM_DEVICE_INFO));
4443 cifs_buf_release(pSMB);
4446 goto QFSDeviceRetry;
4452 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4454 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4455 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4456 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4457 FILE_SYSTEM_UNIX_INFO *response_data;
4459 int bytes_returned = 0;
4460 __u16 params, byte_count;
4462 cFYI(1, ("In QFSUnixInfo"));
4464 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4469 params = 2; /* level */
4470 pSMB->TotalDataCount = 0;
4471 pSMB->DataCount = 0;
4472 pSMB->DataOffset = 0;
4473 pSMB->MaxParameterCount = cpu_to_le16(2);
4474 /* BB find exact max SMB PDU from sess structure BB */
4475 pSMB->MaxDataCount = cpu_to_le16(100);
4476 pSMB->MaxSetupCount = 0;
4480 pSMB->Reserved2 = 0;
4481 byte_count = params + 1 /* pad */ ;
4482 pSMB->ParameterCount = cpu_to_le16(params);
4483 pSMB->TotalParameterCount = pSMB->ParameterCount;
4484 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4485 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4486 pSMB->SetupCount = 1;
4487 pSMB->Reserved3 = 0;
4488 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4489 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4490 pSMB->hdr.smb_buf_length += byte_count;
4491 pSMB->ByteCount = cpu_to_le16(byte_count);
4493 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4494 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4496 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4497 } else { /* decode response */
4498 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4500 if (rc || (pSMBr->ByteCount < 13)) {
4501 rc = -EIO; /* bad smb */
4503 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4505 (FILE_SYSTEM_UNIX_INFO
4506 *) (((char *) &pSMBr->hdr.Protocol) +
4508 memcpy(&tcon->fsUnixInfo, response_data,
4509 sizeof(FILE_SYSTEM_UNIX_INFO));
4512 cifs_buf_release(pSMB);
4522 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4524 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4525 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4526 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4528 int bytes_returned = 0;
4529 __u16 params, param_offset, offset, byte_count;
4531 cFYI(1, ("In SETFSUnixInfo"));
4533 /* BB switch to small buf init to save memory */
4534 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4539 params = 4; /* 2 bytes zero followed by info level. */
4540 pSMB->MaxSetupCount = 0;
4544 pSMB->Reserved2 = 0;
4545 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4547 offset = param_offset + params;
4549 pSMB->MaxParameterCount = cpu_to_le16(4);
4550 /* BB find exact max SMB PDU from sess structure BB */
4551 pSMB->MaxDataCount = cpu_to_le16(100);
4552 pSMB->SetupCount = 1;
4553 pSMB->Reserved3 = 0;
4554 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4555 byte_count = 1 /* pad */ + params + 12;
4557 pSMB->DataCount = cpu_to_le16(12);
4558 pSMB->ParameterCount = cpu_to_le16(params);
4559 pSMB->TotalDataCount = pSMB->DataCount;
4560 pSMB->TotalParameterCount = pSMB->ParameterCount;
4561 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4562 pSMB->DataOffset = cpu_to_le16(offset);
4566 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4569 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4570 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4571 pSMB->ClientUnixCap = cpu_to_le64(cap);
4573 pSMB->hdr.smb_buf_length += byte_count;
4574 pSMB->ByteCount = cpu_to_le16(byte_count);
4576 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4577 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4579 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4580 } else { /* decode response */
4581 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4583 rc = -EIO; /* bad smb */
4585 cifs_buf_release(pSMB);
4588 goto SETFSUnixRetry;
4596 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4597 struct kstatfs *FSData)
4599 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4600 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4601 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4602 FILE_SYSTEM_POSIX_INFO *response_data;
4604 int bytes_returned = 0;
4605 __u16 params, byte_count;
4607 cFYI(1, ("In QFSPosixInfo"));
4609 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4614 params = 2; /* level */
4615 pSMB->TotalDataCount = 0;
4616 pSMB->DataCount = 0;
4617 pSMB->DataOffset = 0;
4618 pSMB->MaxParameterCount = cpu_to_le16(2);
4619 /* BB find exact max SMB PDU from sess structure BB */
4620 pSMB->MaxDataCount = cpu_to_le16(100);
4621 pSMB->MaxSetupCount = 0;
4625 pSMB->Reserved2 = 0;
4626 byte_count = params + 1 /* pad */ ;
4627 pSMB->ParameterCount = cpu_to_le16(params);
4628 pSMB->TotalParameterCount = pSMB->ParameterCount;
4629 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4630 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4631 pSMB->SetupCount = 1;
4632 pSMB->Reserved3 = 0;
4633 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4634 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4635 pSMB->hdr.smb_buf_length += byte_count;
4636 pSMB->ByteCount = cpu_to_le16(byte_count);
4638 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4639 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4641 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4642 } else { /* decode response */
4643 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4645 if (rc || (pSMBr->ByteCount < 13)) {
4646 rc = -EIO; /* bad smb */
4648 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4650 (FILE_SYSTEM_POSIX_INFO
4651 *) (((char *) &pSMBr->hdr.Protocol) +
4654 le32_to_cpu(response_data->BlockSize);
4656 le64_to_cpu(response_data->TotalBlocks);
4658 le64_to_cpu(response_data->BlocksAvail);
4659 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4660 FSData->f_bavail = FSData->f_bfree;
4663 le64_to_cpu(response_data->UserBlocksAvail);
4665 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4667 le64_to_cpu(response_data->TotalFileNodes);
4668 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4670 le64_to_cpu(response_data->FreeFileNodes);
4673 cifs_buf_release(pSMB);
4682 /* We can not use write of zero bytes trick to
4683 set file size due to need for large file support. Also note that
4684 this SetPathInfo is preferred to SetFileInfo based method in next
4685 routine which is only needed to work around a sharing violation bug
4686 in Samba which this routine can run into */
4689 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4690 __u64 size, bool SetAllocation,
4691 const struct nls_table *nls_codepage, int remap)
4693 struct smb_com_transaction2_spi_req *pSMB = NULL;
4694 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4695 struct file_end_of_file_info *parm_data;
4698 int bytes_returned = 0;
4699 __u16 params, byte_count, data_count, param_offset, offset;
4701 cFYI(1, ("In SetEOF"));
4703 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4708 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4710 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4711 PATH_MAX, nls_codepage, remap);
4712 name_len++; /* trailing null */
4714 } else { /* BB improve the check for buffer overruns BB */
4715 name_len = strnlen(fileName, PATH_MAX);
4716 name_len++; /* trailing null */
4717 strncpy(pSMB->FileName, fileName, name_len);
4719 params = 6 + name_len;
4720 data_count = sizeof(struct file_end_of_file_info);
4721 pSMB->MaxParameterCount = cpu_to_le16(2);
4722 pSMB->MaxDataCount = cpu_to_le16(4100);
4723 pSMB->MaxSetupCount = 0;
4727 pSMB->Reserved2 = 0;
4728 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4729 InformationLevel) - 4;
4730 offset = param_offset + params;
4731 if (SetAllocation) {
4732 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4733 pSMB->InformationLevel =
4734 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4736 pSMB->InformationLevel =
4737 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4738 } else /* Set File Size */ {
4739 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4740 pSMB->InformationLevel =
4741 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4743 pSMB->InformationLevel =
4744 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4748 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4750 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4751 pSMB->DataOffset = cpu_to_le16(offset);
4752 pSMB->SetupCount = 1;
4753 pSMB->Reserved3 = 0;
4754 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4755 byte_count = 3 /* pad */ + params + data_count;
4756 pSMB->DataCount = cpu_to_le16(data_count);
4757 pSMB->TotalDataCount = pSMB->DataCount;
4758 pSMB->ParameterCount = cpu_to_le16(params);
4759 pSMB->TotalParameterCount = pSMB->ParameterCount;
4760 pSMB->Reserved4 = 0;
4761 pSMB->hdr.smb_buf_length += byte_count;
4762 parm_data->FileSize = cpu_to_le64(size);
4763 pSMB->ByteCount = cpu_to_le16(byte_count);
4764 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4765 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4767 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4769 cifs_buf_release(pSMB);
4778 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4779 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4781 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4783 struct file_end_of_file_info *parm_data;
4785 __u16 params, param_offset, offset, byte_count, count;
4787 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4789 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4794 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4795 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4798 pSMB->MaxSetupCount = 0;
4802 pSMB->Reserved2 = 0;
4803 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4804 offset = param_offset + params;
4806 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4808 count = sizeof(struct file_end_of_file_info);
4809 pSMB->MaxParameterCount = cpu_to_le16(2);
4810 /* BB find exact max SMB PDU from sess structure BB */
4811 pSMB->MaxDataCount = cpu_to_le16(1000);
4812 pSMB->SetupCount = 1;
4813 pSMB->Reserved3 = 0;
4814 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4815 byte_count = 3 /* pad */ + params + count;
4816 pSMB->DataCount = cpu_to_le16(count);
4817 pSMB->ParameterCount = cpu_to_le16(params);
4818 pSMB->TotalDataCount = pSMB->DataCount;
4819 pSMB->TotalParameterCount = pSMB->ParameterCount;
4820 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4822 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4824 pSMB->DataOffset = cpu_to_le16(offset);
4825 parm_data->FileSize = cpu_to_le64(size);
4827 if (SetAllocation) {
4828 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4829 pSMB->InformationLevel =
4830 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4832 pSMB->InformationLevel =
4833 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4834 } else /* Set File Size */ {
4835 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4836 pSMB->InformationLevel =
4837 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4839 pSMB->InformationLevel =
4840 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4842 pSMB->Reserved4 = 0;
4843 pSMB->hdr.smb_buf_length += byte_count;
4844 pSMB->ByteCount = cpu_to_le16(byte_count);
4845 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4848 ("Send error in SetFileInfo (SetFileSize) = %d",
4852 /* Note: On -EAGAIN error only caller can retry on handle based calls
4853 since file handle passed in no longer valid */
4858 /* Some legacy servers such as NT4 require that the file times be set on
4859 an open handle, rather than by pathname - this is awkward due to
4860 potential access conflicts on the open, but it is unavoidable for these
4861 old servers since the only other choice is to go from 100 nanosecond DCE
4862 time and resort to the original setpathinfo level which takes the ancient
4863 DOS time format with 2 second granularity */
4865 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4866 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4868 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4871 __u16 params, param_offset, offset, byte_count, count;
4873 cFYI(1, ("Set Times (via SetFileInfo)"));
4874 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4879 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4880 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4883 pSMB->MaxSetupCount = 0;
4887 pSMB->Reserved2 = 0;
4888 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4889 offset = param_offset + params;
4891 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4893 count = sizeof(FILE_BASIC_INFO);
4894 pSMB->MaxParameterCount = cpu_to_le16(2);
4895 /* BB find max SMB PDU from sess */
4896 pSMB->MaxDataCount = cpu_to_le16(1000);
4897 pSMB->SetupCount = 1;
4898 pSMB->Reserved3 = 0;
4899 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4900 byte_count = 3 /* pad */ + params + count;
4901 pSMB->DataCount = cpu_to_le16(count);
4902 pSMB->ParameterCount = cpu_to_le16(params);
4903 pSMB->TotalDataCount = pSMB->DataCount;
4904 pSMB->TotalParameterCount = pSMB->ParameterCount;
4905 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4906 pSMB->DataOffset = cpu_to_le16(offset);
4908 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4909 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4911 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4912 pSMB->Reserved4 = 0;
4913 pSMB->hdr.smb_buf_length += byte_count;
4914 pSMB->ByteCount = cpu_to_le16(byte_count);
4915 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4916 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4918 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4920 /* Note: On -EAGAIN error only caller can retry on handle based calls
4921 since file handle passed in no longer valid */
4927 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4928 bool delete_file, __u16 fid, __u32 pid_of_opener)
4930 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4933 __u16 params, param_offset, offset, byte_count, count;
4935 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4936 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4941 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4942 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4945 pSMB->MaxSetupCount = 0;
4949 pSMB->Reserved2 = 0;
4950 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4951 offset = param_offset + params;
4953 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4956 pSMB->MaxParameterCount = cpu_to_le16(2);
4957 /* BB find max SMB PDU from sess */
4958 pSMB->MaxDataCount = cpu_to_le16(1000);
4959 pSMB->SetupCount = 1;
4960 pSMB->Reserved3 = 0;
4961 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4962 byte_count = 3 /* pad */ + params + count;
4963 pSMB->DataCount = cpu_to_le16(count);
4964 pSMB->ParameterCount = cpu_to_le16(params);
4965 pSMB->TotalDataCount = pSMB->DataCount;
4966 pSMB->TotalParameterCount = pSMB->ParameterCount;
4967 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4968 pSMB->DataOffset = cpu_to_le16(offset);
4970 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4971 pSMB->Reserved4 = 0;
4972 pSMB->hdr.smb_buf_length += byte_count;
4973 pSMB->ByteCount = cpu_to_le16(byte_count);
4974 *data_offset = delete_file ? 1 : 0;
4975 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4977 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4983 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4984 const char *fileName, const FILE_BASIC_INFO *data,
4985 const struct nls_table *nls_codepage, int remap)
4987 TRANSACTION2_SPI_REQ *pSMB = NULL;
4988 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4991 int bytes_returned = 0;
4993 __u16 params, param_offset, offset, byte_count, count;
4995 cFYI(1, ("In SetTimes"));
4998 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5005 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5006 PATH_MAX, nls_codepage, remap);
5007 name_len++; /* trailing null */
5009 } else { /* BB improve the check for buffer overruns BB */
5010 name_len = strnlen(fileName, PATH_MAX);
5011 name_len++; /* trailing null */
5012 strncpy(pSMB->FileName, fileName, name_len);
5015 params = 6 + name_len;
5016 count = sizeof(FILE_BASIC_INFO);
5017 pSMB->MaxParameterCount = cpu_to_le16(2);
5018 /* BB find max SMB PDU from sess structure BB */
5019 pSMB->MaxDataCount = cpu_to_le16(1000);
5020 pSMB->MaxSetupCount = 0;
5024 pSMB->Reserved2 = 0;
5025 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5026 InformationLevel) - 4;
5027 offset = param_offset + params;
5028 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5029 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5030 pSMB->DataOffset = cpu_to_le16(offset);
5031 pSMB->SetupCount = 1;
5032 pSMB->Reserved3 = 0;
5033 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5034 byte_count = 3 /* pad */ + params + count;
5036 pSMB->DataCount = cpu_to_le16(count);
5037 pSMB->ParameterCount = cpu_to_le16(params);
5038 pSMB->TotalDataCount = pSMB->DataCount;
5039 pSMB->TotalParameterCount = pSMB->ParameterCount;
5040 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5041 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5043 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5044 pSMB->Reserved4 = 0;
5045 pSMB->hdr.smb_buf_length += byte_count;
5046 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5047 pSMB->ByteCount = cpu_to_le16(byte_count);
5048 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5049 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5051 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5053 cifs_buf_release(pSMB);
5061 /* Can not be used to set time stamps yet (due to old DOS time format) */
5062 /* Can be used to set attributes */
5063 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5064 handling it anyway and NT4 was what we thought it would be needed for
5065 Do not delete it until we prove whether needed for Win9x though */
5067 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5068 __u16 dos_attrs, const struct nls_table *nls_codepage)
5070 SETATTR_REQ *pSMB = NULL;
5071 SETATTR_RSP *pSMBr = NULL;
5076 cFYI(1, ("In SetAttrLegacy"));
5079 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5084 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5086 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5087 PATH_MAX, nls_codepage);
5088 name_len++; /* trailing null */
5090 } else { /* BB improve the check for buffer overruns BB */
5091 name_len = strnlen(fileName, PATH_MAX);
5092 name_len++; /* trailing null */
5093 strncpy(pSMB->fileName, fileName, name_len);
5095 pSMB->attr = cpu_to_le16(dos_attrs);
5096 pSMB->BufferFormat = 0x04;
5097 pSMB->hdr.smb_buf_length += name_len + 1;
5098 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5099 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5100 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5102 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5104 cifs_buf_release(pSMB);
5107 goto SetAttrLgcyRetry;
5111 #endif /* temporarily unneeded SetAttr legacy function */
5114 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5115 const struct cifs_unix_set_info_args *args,
5116 const struct nls_table *nls_codepage, int remap)
5118 TRANSACTION2_SPI_REQ *pSMB = NULL;
5119 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5122 int bytes_returned = 0;
5123 FILE_UNIX_BASIC_INFO *data_offset;
5124 __u16 params, param_offset, offset, count, byte_count;
5125 __u64 mode = args->mode;
5127 cFYI(1, ("In SetUID/GID/Mode"));
5129 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5134 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5136 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5137 PATH_MAX, nls_codepage, remap);
5138 name_len++; /* trailing null */
5140 } else { /* BB improve the check for buffer overruns BB */
5141 name_len = strnlen(fileName, PATH_MAX);
5142 name_len++; /* trailing null */
5143 strncpy(pSMB->FileName, fileName, name_len);
5146 params = 6 + name_len;
5147 count = sizeof(FILE_UNIX_BASIC_INFO);
5148 pSMB->MaxParameterCount = cpu_to_le16(2);
5149 /* BB find max SMB PDU from sess structure BB */
5150 pSMB->MaxDataCount = cpu_to_le16(1000);
5151 pSMB->MaxSetupCount = 0;
5155 pSMB->Reserved2 = 0;
5156 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5157 InformationLevel) - 4;
5158 offset = param_offset + params;
5160 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5162 memset(data_offset, 0, count);
5163 pSMB->DataOffset = cpu_to_le16(offset);
5164 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5165 pSMB->SetupCount = 1;
5166 pSMB->Reserved3 = 0;
5167 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5168 byte_count = 3 /* pad */ + params + count;
5169 pSMB->ParameterCount = cpu_to_le16(params);
5170 pSMB->DataCount = cpu_to_le16(count);
5171 pSMB->TotalParameterCount = pSMB->ParameterCount;
5172 pSMB->TotalDataCount = pSMB->DataCount;
5173 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5174 pSMB->Reserved4 = 0;
5175 pSMB->hdr.smb_buf_length += byte_count;
5176 /* Samba server ignores set of file size to zero due to bugs in some
5177 older clients, but we should be precise - we use SetFileSize to
5178 set file size and do not want to truncate file size to zero
5179 accidently as happened on one Samba server beta by putting
5180 zero instead of -1 here */
5181 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5182 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5183 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5184 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5185 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5186 data_offset->Uid = cpu_to_le64(args->uid);
5187 data_offset->Gid = cpu_to_le64(args->gid);
5188 /* better to leave device as zero when it is */
5189 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5190 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5191 data_offset->Permissions = cpu_to_le64(mode);
5194 data_offset->Type = cpu_to_le32(UNIX_FILE);
5195 else if (S_ISDIR(mode))
5196 data_offset->Type = cpu_to_le32(UNIX_DIR);
5197 else if (S_ISLNK(mode))
5198 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5199 else if (S_ISCHR(mode))
5200 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5201 else if (S_ISBLK(mode))
5202 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5203 else if (S_ISFIFO(mode))
5204 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5205 else if (S_ISSOCK(mode))
5206 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5209 pSMB->ByteCount = cpu_to_le16(byte_count);
5210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5213 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5215 cifs_buf_release(pSMB);
5221 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5222 const int notify_subdirs, const __u16 netfid,
5223 __u32 filter, struct file *pfile, int multishot,
5224 const struct nls_table *nls_codepage)
5227 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5228 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5229 struct dir_notify_req *dnotify_req;
5232 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5233 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5238 pSMB->TotalParameterCount = 0 ;
5239 pSMB->TotalDataCount = 0;
5240 pSMB->MaxParameterCount = cpu_to_le32(2);
5241 /* BB find exact data count max from sess structure BB */
5242 pSMB->MaxDataCount = 0; /* same in little endian or be */
5243 /* BB VERIFY verify which is correct for above BB */
5244 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5245 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5247 pSMB->MaxSetupCount = 4;
5249 pSMB->ParameterOffset = 0;
5250 pSMB->DataCount = 0;
5251 pSMB->DataOffset = 0;
5252 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5253 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5254 pSMB->ParameterCount = pSMB->TotalParameterCount;
5256 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5257 pSMB->Reserved2 = 0;
5258 pSMB->CompletionFilter = cpu_to_le32(filter);
5259 pSMB->Fid = netfid; /* file handle always le */
5260 pSMB->ByteCount = 0;
5262 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5263 (struct smb_hdr *)pSMBr, &bytes_returned,
5266 cFYI(1, ("Error in Notify = %d", rc));
5268 /* Add file to outstanding requests */
5269 /* BB change to kmem cache alloc */
5270 dnotify_req = kmalloc(
5271 sizeof(struct dir_notify_req),
5274 dnotify_req->Pid = pSMB->hdr.Pid;
5275 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5276 dnotify_req->Mid = pSMB->hdr.Mid;
5277 dnotify_req->Tid = pSMB->hdr.Tid;
5278 dnotify_req->Uid = pSMB->hdr.Uid;
5279 dnotify_req->netfid = netfid;
5280 dnotify_req->pfile = pfile;
5281 dnotify_req->filter = filter;
5282 dnotify_req->multishot = multishot;
5283 spin_lock(&GlobalMid_Lock);
5284 list_add_tail(&dnotify_req->lhead,
5285 &GlobalDnotifyReqList);
5286 spin_unlock(&GlobalMid_Lock);
5290 cifs_buf_release(pSMB);
5293 #ifdef CONFIG_CIFS_XATTR
5295 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5296 const unsigned char *searchName,
5297 char *EAData, size_t buf_size,
5298 const struct nls_table *nls_codepage, int remap)
5300 /* BB assumes one setup word */
5301 TRANSACTION2_QPI_REQ *pSMB = NULL;
5302 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5306 struct fea *temp_fea;
5308 __u16 params, byte_count;
5310 cFYI(1, ("In Query All EAs path %s", searchName));
5312 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5317 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5319 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5320 PATH_MAX, nls_codepage, remap);
5321 name_len++; /* trailing null */
5323 } else { /* BB improve the check for buffer overruns BB */
5324 name_len = strnlen(searchName, PATH_MAX);
5325 name_len++; /* trailing null */
5326 strncpy(pSMB->FileName, searchName, name_len);
5329 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5330 pSMB->TotalDataCount = 0;
5331 pSMB->MaxParameterCount = cpu_to_le16(2);
5332 /* BB find exact max SMB PDU from sess structure BB */
5333 pSMB->MaxDataCount = cpu_to_le16(4000);
5334 pSMB->MaxSetupCount = 0;
5338 pSMB->Reserved2 = 0;
5339 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5340 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5341 pSMB->DataCount = 0;
5342 pSMB->DataOffset = 0;
5343 pSMB->SetupCount = 1;
5344 pSMB->Reserved3 = 0;
5345 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5346 byte_count = params + 1 /* pad */ ;
5347 pSMB->TotalParameterCount = cpu_to_le16(params);
5348 pSMB->ParameterCount = pSMB->TotalParameterCount;
5349 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5350 pSMB->Reserved4 = 0;
5351 pSMB->hdr.smb_buf_length += byte_count;
5352 pSMB->ByteCount = cpu_to_le16(byte_count);
5354 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5355 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5357 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5358 } else { /* decode response */
5359 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5361 /* BB also check enough total bytes returned */
5362 /* BB we need to improve the validity checking
5363 of these trans2 responses */
5364 if (rc || (pSMBr->ByteCount < 4))
5365 rc = -EIO; /* bad smb */
5366 /* else if (pFindData){
5367 memcpy((char *) pFindData,
5368 (char *) &pSMBr->hdr.Protocol +
5371 /* check that length of list is not more than bcc */
5372 /* check that each entry does not go beyond length
5374 /* check that each element of each entry does not
5375 go beyond end of list */
5376 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5377 struct fealist *ea_response_data;
5379 /* validate_trans2_offsets() */
5380 /* BB check if start of smb + data_offset > &bcc+ bcc */
5381 ea_response_data = (struct fealist *)
5382 (((char *) &pSMBr->hdr.Protocol) +
5384 name_len = le32_to_cpu(ea_response_data->list_len);
5385 cFYI(1, ("ea length %d", name_len));
5386 if (name_len <= 8) {
5387 /* returned EA size zeroed at top of function */
5388 cFYI(1, ("empty EA list returned from server"));
5390 /* account for ea list len */
5392 temp_fea = ea_response_data->list;
5393 temp_ptr = (char *)temp_fea;
5394 while (name_len > 0) {
5398 rc += temp_fea->name_len;
5399 /* account for prefix user. and trailing null */
5401 if (rc < (int)buf_size) {
5402 memcpy(EAData, "user.", 5);
5404 memcpy(EAData, temp_ptr,
5405 temp_fea->name_len);
5406 EAData += temp_fea->name_len;
5407 /* null terminate name */
5409 EAData = EAData + 1;
5410 } else if (buf_size == 0) {
5411 /* skip copy - calc size only */
5413 /* stop before overrun buffer */
5417 name_len -= temp_fea->name_len;
5418 temp_ptr += temp_fea->name_len;
5419 /* account for trailing null */
5423 le16_to_cpu(temp_fea->value_len);
5424 name_len -= value_len;
5425 temp_ptr += value_len;
5426 /* BB check that temp_ptr is still
5429 /* no trailing null to account for
5431 /* go on to next EA */
5432 temp_fea = (struct fea *)temp_ptr;
5437 cifs_buf_release(pSMB);
5444 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5445 const unsigned char *searchName, const unsigned char *ea_name,
5446 unsigned char *ea_value, size_t buf_size,
5447 const struct nls_table *nls_codepage, int remap)
5449 TRANSACTION2_QPI_REQ *pSMB = NULL;
5450 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5454 struct fea *temp_fea;
5456 __u16 params, byte_count;
5458 cFYI(1, ("In Query EA path %s", searchName));
5460 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5465 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5467 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5468 PATH_MAX, nls_codepage, remap);
5469 name_len++; /* trailing null */
5471 } else { /* BB improve the check for buffer overruns BB */
5472 name_len = strnlen(searchName, PATH_MAX);
5473 name_len++; /* trailing null */
5474 strncpy(pSMB->FileName, searchName, name_len);
5477 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5478 pSMB->TotalDataCount = 0;
5479 pSMB->MaxParameterCount = cpu_to_le16(2);
5480 /* BB find exact max SMB PDU from sess structure BB */
5481 pSMB->MaxDataCount = cpu_to_le16(4000);
5482 pSMB->MaxSetupCount = 0;
5486 pSMB->Reserved2 = 0;
5487 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5488 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5489 pSMB->DataCount = 0;
5490 pSMB->DataOffset = 0;
5491 pSMB->SetupCount = 1;
5492 pSMB->Reserved3 = 0;
5493 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5494 byte_count = params + 1 /* pad */ ;
5495 pSMB->TotalParameterCount = cpu_to_le16(params);
5496 pSMB->ParameterCount = pSMB->TotalParameterCount;
5497 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5498 pSMB->Reserved4 = 0;
5499 pSMB->hdr.smb_buf_length += byte_count;
5500 pSMB->ByteCount = cpu_to_le16(byte_count);
5502 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5505 cFYI(1, ("Send error in Query EA = %d", rc));
5506 } else { /* decode response */
5507 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5509 /* BB also check enough total bytes returned */
5510 /* BB we need to improve the validity checking
5511 of these trans2 responses */
5512 if (rc || (pSMBr->ByteCount < 4))
5513 rc = -EIO; /* bad smb */
5514 /* else if (pFindData){
5515 memcpy((char *) pFindData,
5516 (char *) &pSMBr->hdr.Protocol +
5519 /* check that length of list is not more than bcc */
5520 /* check that each entry does not go beyond length
5522 /* check that each element of each entry does not
5523 go beyond end of list */
5524 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5525 struct fealist *ea_response_data;
5527 /* validate_trans2_offsets() */
5528 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5529 ea_response_data = (struct fealist *)
5530 (((char *) &pSMBr->hdr.Protocol) +
5532 name_len = le32_to_cpu(ea_response_data->list_len);
5533 cFYI(1, ("ea length %d", name_len));
5534 if (name_len <= 8) {
5535 /* returned EA size zeroed at top of function */
5536 cFYI(1, ("empty EA list returned from server"));
5538 /* account for ea list len */
5540 temp_fea = ea_response_data->list;
5541 temp_ptr = (char *)temp_fea;
5542 /* loop through checking if we have a matching
5543 name and then return the associated value */
5544 while (name_len > 0) {
5549 le16_to_cpu(temp_fea->value_len);
5550 /* BB validate that value_len falls within SMB,
5551 even though maximum for name_len is 255 */
5552 if (memcmp(temp_fea->name, ea_name,
5553 temp_fea->name_len) == 0) {
5556 /* account for prefix user. and trailing null */
5557 if (rc <= (int)buf_size) {
5559 temp_fea->name+temp_fea->name_len+1,
5561 /* ea values, unlike ea
5564 } else if (buf_size == 0) {
5565 /* skip copy - calc size only */
5567 /* stop before overrun buffer */
5572 name_len -= temp_fea->name_len;
5573 temp_ptr += temp_fea->name_len;
5574 /* account for trailing null */
5577 name_len -= value_len;
5578 temp_ptr += value_len;
5579 /* No trailing null to account for in
5580 value_len. Go on to next EA */
5581 temp_fea = (struct fea *)temp_ptr;
5586 cifs_buf_release(pSMB);
5594 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5595 const char *ea_name, const void *ea_value,
5596 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5599 struct smb_com_transaction2_spi_req *pSMB = NULL;
5600 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5601 struct fealist *parm_data;
5604 int bytes_returned = 0;
5605 __u16 params, param_offset, byte_count, offset, count;
5607 cFYI(1, ("In SetEA"));
5609 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5614 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5616 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5617 PATH_MAX, nls_codepage, remap);
5618 name_len++; /* trailing null */
5620 } else { /* BB improve the check for buffer overruns BB */
5621 name_len = strnlen(fileName, PATH_MAX);
5622 name_len++; /* trailing null */
5623 strncpy(pSMB->FileName, fileName, name_len);
5626 params = 6 + name_len;
5628 /* done calculating parms using name_len of file name,
5629 now use name_len to calculate length of ea name
5630 we are going to create in the inode xattrs */
5631 if (ea_name == NULL)
5634 name_len = strnlen(ea_name, 255);
5636 count = sizeof(*parm_data) + ea_value_len + name_len;
5637 pSMB->MaxParameterCount = cpu_to_le16(2);
5638 /* BB find max SMB PDU from sess */
5639 pSMB->MaxDataCount = cpu_to_le16(1000);
5640 pSMB->MaxSetupCount = 0;
5644 pSMB->Reserved2 = 0;
5645 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5646 InformationLevel) - 4;
5647 offset = param_offset + params;
5648 pSMB->InformationLevel =
5649 cpu_to_le16(SMB_SET_FILE_EA);
5652 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5654 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5655 pSMB->DataOffset = cpu_to_le16(offset);
5656 pSMB->SetupCount = 1;
5657 pSMB->Reserved3 = 0;
5658 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5659 byte_count = 3 /* pad */ + params + count;
5660 pSMB->DataCount = cpu_to_le16(count);
5661 parm_data->list_len = cpu_to_le32(count);
5662 parm_data->list[0].EA_flags = 0;
5663 /* we checked above that name len is less than 255 */
5664 parm_data->list[0].name_len = (__u8)name_len;
5665 /* EA names are always ASCII */
5667 strncpy(parm_data->list[0].name, ea_name, name_len);
5668 parm_data->list[0].name[name_len] = 0;
5669 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5670 /* caller ensures that ea_value_len is less than 64K but
5671 we need to ensure that it fits within the smb */
5673 /*BB add length check to see if it would fit in
5674 negotiated SMB buffer size BB */
5675 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5677 memcpy(parm_data->list[0].name+name_len+1,
5678 ea_value, ea_value_len);
5680 pSMB->TotalDataCount = pSMB->DataCount;
5681 pSMB->ParameterCount = cpu_to_le16(params);
5682 pSMB->TotalParameterCount = pSMB->ParameterCount;
5683 pSMB->Reserved4 = 0;
5684 pSMB->hdr.smb_buf_length += byte_count;
5685 pSMB->ByteCount = cpu_to_le16(byte_count);
5686 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5687 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5689 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5691 cifs_buf_release(pSMB);