4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
42 #ifdef CONFIG_CIFS_POSIX
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48 {LANMAN_PROT, "\2LM1.2X002"},
49 {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51 {CIFS_PROT, "\2NT LM 0.12"},
52 {POSIX_PROT, "\2POSIX 2"},
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61 {LANMAN_PROT, "\2LM1.2X002"},
62 {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64 {CIFS_PROT, "\2NT LM 0.12"},
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
84 /* Allocates buffer into dst and copies smb string from src to it.
85 * caller is responsible for freeing dst if function returned 0.
91 cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92 const bool is_unicode, const struct nls_table *nls_codepage)
97 plen = UniStrnlen((wchar_t *)src, maxlen);
98 *dst = kmalloc(plen + 2, GFP_KERNEL);
100 goto cifs_strncpy_to_host_ErrExit;
101 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
103 plen = strnlen(src, maxlen);
104 *dst = kmalloc(plen + 2, GFP_KERNEL);
106 goto cifs_strncpy_to_host_ErrExit;
107 strncpy(*dst, src, plen);
110 (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
113 cifs_strncpy_to_host_ErrExit:
114 cERROR(1, ("Failed to allocate buffer for string\n"));
119 /* Mark as invalid, all open files on tree connections since they
120 were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
123 struct cifsFileInfo *open_file = NULL;
124 struct list_head *tmp;
125 struct list_head *tmp1;
127 /* list all files open on tree connection and mark them invalid */
128 write_lock(&GlobalSMBSeslock);
129 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
131 open_file->invalidHandle = true;
133 write_unlock(&GlobalSMBSeslock);
134 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
138 /* Allocate and return pointer to an SMB request buffer, and set basic
139 SMB information in the SMB header. If the return code is zero, this
140 function must have filled in request_buf pointer */
142 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
147 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
148 check for tcp and smb session status done differently
149 for those three - in the calling routine */
151 if (tcon->tidStatus == CifsExiting) {
152 /* only tree disconnect, open, and write,
153 (and ulogoff which does not have tcon)
154 are allowed as we start force umount */
155 if ((smb_command != SMB_COM_WRITE_ANDX) &&
156 (smb_command != SMB_COM_OPEN_ANDX) &&
157 (smb_command != SMB_COM_TREE_DISCONNECT)) {
158 cFYI(1, ("can not send cmd %d while umounting",
163 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
164 (tcon->ses->server)) {
165 struct nls_table *nls_codepage;
166 /* Give Demultiplex thread up to 10 seconds to
167 reconnect, should be greater than cifs socket
168 timeout which is 7 seconds */
169 while (tcon->ses->server->tcpStatus ==
171 wait_event_interruptible_timeout(tcon->ses->server->response_q,
172 (tcon->ses->server->tcpStatus ==
174 if (tcon->ses->server->tcpStatus ==
176 /* on "soft" mounts we wait once */
178 (tcon->ses->status == CifsExiting)) {
179 cFYI(1, ("gave up waiting on "
180 "reconnect in smb_init"));
182 } /* else "hard" mount - keep retrying
183 until process is killed or server
184 comes back on-line */
185 } else /* TCP session is reestablished now */
189 nls_codepage = load_nls_default();
190 /* need to prevent multiple threads trying to
191 simultaneously reconnect the same SMB session */
192 down(&tcon->ses->sesSem);
193 if (tcon->ses->need_reconnect)
194 rc = cifs_setup_session(0, tcon->ses,
196 if (!rc && (tcon->need_reconnect)) {
197 mark_open_files_invalid(tcon);
198 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
200 up(&tcon->ses->sesSem);
201 /* BB FIXME add code to check if wsize needs
202 update due to negotiated smb buffer size
205 atomic_inc(&tconInfoReconnectCount);
206 /* tell server Unix caps we support */
207 if (tcon->ses->capabilities & CAP_UNIX)
208 reset_cifs_unix_caps(
211 NULL /* we do not know sb */,
212 NULL /* no vol info */);
215 cFYI(1, ("reconnect tcon rc = %d", rc));
216 /* Removed call to reopen open files here.
217 It is safer (and faster) to reopen files
218 one at a time as needed in read and write */
220 /* Check if handle based operation so we
221 know whether we can continue or not without
222 returning to caller to reset file handle */
223 switch (smb_command) {
224 case SMB_COM_READ_ANDX:
225 case SMB_COM_WRITE_ANDX:
227 case SMB_COM_FIND_CLOSE2:
228 case SMB_COM_LOCKING_ANDX: {
229 unload_nls(nls_codepage);
234 up(&tcon->ses->sesSem);
236 unload_nls(nls_codepage);
245 *request_buf = cifs_small_buf_get();
246 if (*request_buf == NULL) {
247 /* BB should we add a retry in here if not a writepage? */
251 header_assemble((struct smb_hdr *) *request_buf, smb_command,
255 cifs_stats_inc(&tcon->num_smbs_sent);
261 small_smb_init_no_tc(const int smb_command, const int wct,
262 struct cifsSesInfo *ses, void **request_buf)
265 struct smb_hdr *buffer;
267 rc = small_smb_init(smb_command, wct, NULL, request_buf);
271 buffer = (struct smb_hdr *)*request_buf;
272 buffer->Mid = GetNextMid(ses->server);
273 if (ses->capabilities & CAP_UNICODE)
274 buffer->Flags2 |= SMBFLG2_UNICODE;
275 if (ses->capabilities & CAP_STATUS32)
276 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
278 /* uid, tid can stay at zero as set in header assemble */
280 /* BB add support for turning on the signing when
281 this function is used after 1st of session setup requests */
286 /* If the return code is zero, this function must fill in request_buf pointer */
288 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
289 void **request_buf /* returned */ ,
290 void **response_buf /* returned */ )
294 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
295 check for tcp and smb session status done differently
296 for those three - in the calling routine */
298 if (tcon->need_reconnect) {
299 /* only tree disconnect, open, and write,
300 (and ulogoff which does not have tcon)
301 are allowed as we start force umount */
302 if ((smb_command != SMB_COM_WRITE_ANDX) &&
303 (smb_command != SMB_COM_OPEN_ANDX) &&
304 (smb_command != SMB_COM_TREE_DISCONNECT)) {
305 cFYI(1, ("can not send cmd %d while umounting",
311 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
312 (tcon->ses->server)) {
313 struct nls_table *nls_codepage;
314 /* Give Demultiplex thread up to 10 seconds to
315 reconnect, should be greater than cifs socket
316 timeout which is 7 seconds */
317 while (tcon->ses->server->tcpStatus ==
319 wait_event_interruptible_timeout(tcon->ses->server->response_q,
320 (tcon->ses->server->tcpStatus ==
322 if (tcon->ses->server->tcpStatus ==
324 /* on "soft" mounts we wait once */
326 (tcon->ses->status == CifsExiting)) {
327 cFYI(1, ("gave up waiting on "
328 "reconnect in smb_init"));
330 } /* else "hard" mount - keep retrying
331 until process is killed or server
333 } else /* TCP session is reestablished now */
336 nls_codepage = load_nls_default();
337 /* need to prevent multiple threads trying to
338 simultaneously reconnect the same SMB session */
339 down(&tcon->ses->sesSem);
340 if (tcon->ses->need_reconnect)
341 rc = cifs_setup_session(0, tcon->ses,
343 if (!rc && (tcon->need_reconnect)) {
344 mark_open_files_invalid(tcon);
345 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
347 up(&tcon->ses->sesSem);
348 /* BB FIXME add code to check if wsize needs
349 update due to negotiated smb buffer size
352 atomic_inc(&tconInfoReconnectCount);
353 /* tell server Unix caps we support */
354 if (tcon->ses->capabilities & CAP_UNIX)
355 reset_cifs_unix_caps(
358 NULL /* do not know sb */,
359 NULL /* no vol info */);
362 cFYI(1, ("reconnect tcon rc = %d", rc));
363 /* Removed call to reopen open files here.
364 It is safer (and faster) to reopen files
365 one at a time as needed in read and write */
367 /* Check if handle based operation so we
368 know whether we can continue or not without
369 returning to caller to reset file handle */
370 switch (smb_command) {
371 case SMB_COM_READ_ANDX:
372 case SMB_COM_WRITE_ANDX:
374 case SMB_COM_FIND_CLOSE2:
375 case SMB_COM_LOCKING_ANDX: {
376 unload_nls(nls_codepage);
381 up(&tcon->ses->sesSem);
383 unload_nls(nls_codepage);
392 *request_buf = cifs_buf_get();
393 if (*request_buf == NULL) {
394 /* BB should we add a retry in here if not a writepage? */
397 /* Although the original thought was we needed the response buf for */
398 /* potential retries of smb operations it turns out we can determine */
399 /* from the mid flags when the request buffer can be resent without */
400 /* having to use a second distinct buffer for the response */
402 *response_buf = *request_buf;
404 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
408 cifs_stats_inc(&tcon->num_smbs_sent);
413 static int validate_t2(struct smb_t2_rsp *pSMB)
419 /* check for plausible wct, bcc and t2 data and parm sizes */
420 /* check for parm and data offset going beyond end of smb */
421 if (pSMB->hdr.WordCount >= 10) {
422 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
423 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
424 /* check that bcc is at least as big as parms + data */
425 /* check that bcc is less than negotiated smb buffer */
426 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
427 if (total_size < 512) {
429 le16_to_cpu(pSMB->t2_rsp.DataCount);
430 /* BCC le converted in SendReceive */
431 pBCC = (pSMB->hdr.WordCount * 2) +
432 sizeof(struct smb_hdr) +
434 if ((total_size <= (*(u16 *)pBCC)) &&
436 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
442 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
443 sizeof(struct smb_t2_rsp) + 16);
447 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
450 NEGOTIATE_RSP *pSMBr;
454 struct TCP_Server_Info *server;
456 unsigned int secFlags;
460 server = ses->server;
465 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
466 (void **) &pSMB, (void **) &pSMBr);
470 /* if any of auth flags (ie not sign or seal) are overriden use them */
471 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
472 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
473 else /* if override flags set only sign/seal OR them with global auth */
474 secFlags = extended_security | ses->overrideSecFlg;
476 cFYI(1, ("secFlags 0x%x", secFlags));
478 pSMB->hdr.Mid = GetNextMid(server);
479 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
481 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
482 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
483 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
484 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
489 for (i = 0; i < CIFS_NUM_PROT; i++) {
490 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
491 count += strlen(protocols[i].name) + 1;
492 /* null at end of source and target buffers anyway */
494 pSMB->hdr.smb_buf_length += count;
495 pSMB->ByteCount = cpu_to_le16(count);
497 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
502 dialect = le16_to_cpu(pSMBr->DialectIndex);
503 cFYI(1, ("Dialect: %d", dialect));
504 /* Check wct = 1 error case */
505 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
506 /* core returns wct = 1, but we do not ask for core - otherwise
507 small wct just comes when dialect index is -1 indicating we
508 could not negotiate a common dialect */
511 #ifdef CONFIG_CIFS_WEAK_PW_HASH
512 } else if ((pSMBr->hdr.WordCount == 13)
513 && ((dialect == LANMAN_PROT)
514 || (dialect == LANMAN2_PROT))) {
516 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
518 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
519 (secFlags & CIFSSEC_MAY_PLNTXT))
520 server->secType = LANMAN;
522 cERROR(1, ("mount failed weak security disabled"
523 " in /proc/fs/cifs/SecurityFlags"));
527 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
528 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
529 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
530 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
531 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
532 /* even though we do not use raw we might as well set this
533 accurately, in case we ever find a need for it */
534 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
535 server->maxRw = 0xFF00;
536 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
538 server->maxRw = 0;/* we do not need to use raw anyway */
539 server->capabilities = CAP_MPX_MODE;
541 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
543 /* OS/2 often does not set timezone therefore
544 * we must use server time to calc time zone.
545 * Could deviate slightly from the right zone.
546 * Smallest defined timezone difference is 15 minutes
547 * (i.e. Nepal). Rounding up/down is done to match
550 int val, seconds, remain, result;
551 struct timespec ts, utc;
553 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
554 le16_to_cpu(rsp->SrvTime.Time));
555 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
556 (int)ts.tv_sec, (int)utc.tv_sec,
557 (int)(utc.tv_sec - ts.tv_sec)));
558 val = (int)(utc.tv_sec - ts.tv_sec);
560 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
561 remain = seconds % MIN_TZ_ADJ;
562 if (remain >= (MIN_TZ_ADJ / 2))
563 result += MIN_TZ_ADJ;
566 server->timeAdj = result;
568 server->timeAdj = (int)tmp;
569 server->timeAdj *= 60; /* also in seconds */
571 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
574 /* BB get server time for time conversions and add
575 code to use it and timezone since this is not UTC */
577 if (rsp->EncryptionKeyLength ==
578 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
579 memcpy(server->cryptKey, rsp->EncryptionKey,
580 CIFS_CRYPTO_KEY_SIZE);
581 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
582 rc = -EIO; /* need cryptkey unless plain text */
586 cFYI(1, ("LANMAN negotiated"));
587 /* we will not end up setting signing flags - as no signing
588 was in LANMAN and server did not return the flags on */
590 #else /* weak security disabled */
591 } else if (pSMBr->hdr.WordCount == 13) {
592 cERROR(1, ("mount failed, cifs module not built "
593 "with CIFS_WEAK_PW_HASH support"));
595 #endif /* WEAK_PW_HASH */
597 } else if (pSMBr->hdr.WordCount != 17) {
602 /* else wct == 17 NTLM */
603 server->secMode = pSMBr->SecurityMode;
604 if ((server->secMode & SECMODE_USER) == 0)
605 cFYI(1, ("share mode security"));
607 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
608 #ifdef CONFIG_CIFS_WEAK_PW_HASH
609 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
610 #endif /* CIFS_WEAK_PW_HASH */
611 cERROR(1, ("Server requests plain text password"
612 " but client support disabled"));
614 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
615 server->secType = NTLMv2;
616 else if (secFlags & CIFSSEC_MAY_NTLM)
617 server->secType = NTLM;
618 else if (secFlags & CIFSSEC_MAY_NTLMV2)
619 server->secType = NTLMv2;
620 else if (secFlags & CIFSSEC_MAY_KRB5)
621 server->secType = Kerberos;
622 else if (secFlags & CIFSSEC_MAY_LANMAN)
623 server->secType = LANMAN;
624 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
625 else if (secFlags & CIFSSEC_MAY_PLNTXT)
630 cERROR(1, ("Invalid security type"));
633 /* else ... any others ...? */
635 /* one byte, so no need to convert this or EncryptionKeyLen from
637 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
638 /* probably no need to store and check maxvcs */
639 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
640 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
641 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
642 cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
643 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
644 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
645 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
646 server->timeAdj *= 60;
647 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
648 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
649 CIFS_CRYPTO_KEY_SIZE);
650 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
651 && (pSMBr->EncryptionKeyLength == 0)) {
652 /* decode security blob */
653 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
654 rc = -EIO; /* no crypt key only if plain text pwd */
658 /* BB might be helpful to save off the domain of server here */
660 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
661 (server->capabilities & CAP_EXTENDED_SECURITY)) {
662 count = pSMBr->ByteCount;
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 * If last user of the connection and
747 * connection alive - disconnect it
748 * If this is the last connection on the server session disconnect it
749 * (and inside session disconnect we should check if tcp socket needs
750 * to be freed and kernel thread woken up).
753 down(&tcon->tconSem);
757 atomic_dec(&tcon->useCount);
758 if (atomic_read(&tcon->useCount) > 0) {
763 /* No need to return error on this operation if tid invalidated and
764 closed on server already e.g. due to tcp session crashing */
765 if (tcon->need_reconnect) {
770 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
774 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
775 (void **)&smb_buffer);
781 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
783 cFYI(1, ("Tree disconnect failed %d", rc));
787 /* No need to return error on this operation if tid invalidated and
788 closed on server already e.g. due to tcp session crashing */
796 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
798 LOGOFF_ANDX_REQ *pSMB;
801 cFYI(1, ("In SMBLogoff for session disconnect"));
804 * BB: do we need to check validity of ses and server? They should
805 * always be valid since we have an active reference. If not, that
806 * should probably be a BUG()
808 if (!ses || !ses->server)
812 if (ses->need_reconnect)
813 goto session_already_dead; /* no need to send SMBlogoff if uid
814 already closed due to reconnect */
815 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
821 pSMB->hdr.Mid = GetNextMid(ses->server);
823 if (ses->server->secMode &
824 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
825 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
827 pSMB->hdr.Uid = ses->Suid;
829 pSMB->AndXCommand = 0xFF;
830 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
831 session_already_dead:
834 /* if session dead then we do not need to do ulogoff,
835 since server closed smb session, no sense reporting
843 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
844 __u16 type, const struct nls_table *nls_codepage, int remap)
846 TRANSACTION2_SPI_REQ *pSMB = NULL;
847 TRANSACTION2_SPI_RSP *pSMBr = NULL;
848 struct unlink_psx_rq *pRqD;
851 int bytes_returned = 0;
852 __u16 params, param_offset, offset, byte_count;
854 cFYI(1, ("In POSIX delete"));
856 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
861 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
863 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
864 PATH_MAX, nls_codepage, remap);
865 name_len++; /* trailing null */
867 } else { /* BB add path length overrun check */
868 name_len = strnlen(fileName, PATH_MAX);
869 name_len++; /* trailing null */
870 strncpy(pSMB->FileName, fileName, name_len);
873 params = 6 + name_len;
874 pSMB->MaxParameterCount = cpu_to_le16(2);
875 pSMB->MaxDataCount = 0; /* BB double check this with jra */
876 pSMB->MaxSetupCount = 0;
881 param_offset = offsetof(struct smb_com_transaction2_spi_req,
882 InformationLevel) - 4;
883 offset = param_offset + params;
885 /* Setup pointer to Request Data (inode type) */
886 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
887 pRqD->type = cpu_to_le16(type);
888 pSMB->ParameterOffset = cpu_to_le16(param_offset);
889 pSMB->DataOffset = cpu_to_le16(offset);
890 pSMB->SetupCount = 1;
892 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
893 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
895 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
896 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
897 pSMB->ParameterCount = cpu_to_le16(params);
898 pSMB->TotalParameterCount = pSMB->ParameterCount;
899 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
901 pSMB->hdr.smb_buf_length += byte_count;
902 pSMB->ByteCount = cpu_to_le16(byte_count);
903 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
904 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
906 cFYI(1, ("Posix delete returned %d", rc));
907 cifs_buf_release(pSMB);
909 cifs_stats_inc(&tcon->num_deletes);
918 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
919 const struct nls_table *nls_codepage, int remap)
921 DELETE_FILE_REQ *pSMB = NULL;
922 DELETE_FILE_RSP *pSMBr = NULL;
928 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
935 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
936 PATH_MAX, nls_codepage, remap);
937 name_len++; /* trailing null */
939 } else { /* BB improve check for buffer overruns BB */
940 name_len = strnlen(fileName, PATH_MAX);
941 name_len++; /* trailing null */
942 strncpy(pSMB->fileName, fileName, name_len);
944 pSMB->SearchAttributes =
945 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
946 pSMB->BufferFormat = 0x04;
947 pSMB->hdr.smb_buf_length += name_len + 1;
948 pSMB->ByteCount = cpu_to_le16(name_len + 1);
949 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
950 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
951 cifs_stats_inc(&tcon->num_deletes);
953 cFYI(1, ("Error in RMFile = %d", rc));
955 cifs_buf_release(pSMB);
963 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
964 const struct nls_table *nls_codepage, int remap)
966 DELETE_DIRECTORY_REQ *pSMB = NULL;
967 DELETE_DIRECTORY_RSP *pSMBr = NULL;
972 cFYI(1, ("In CIFSSMBRmDir"));
974 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
979 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
980 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
981 PATH_MAX, nls_codepage, remap);
982 name_len++; /* trailing null */
984 } else { /* BB improve check for buffer overruns BB */
985 name_len = strnlen(dirName, PATH_MAX);
986 name_len++; /* trailing null */
987 strncpy(pSMB->DirName, dirName, name_len);
990 pSMB->BufferFormat = 0x04;
991 pSMB->hdr.smb_buf_length += name_len + 1;
992 pSMB->ByteCount = cpu_to_le16(name_len + 1);
993 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
994 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
995 cifs_stats_inc(&tcon->num_rmdirs);
997 cFYI(1, ("Error in RMDir = %d", rc));
999 cifs_buf_release(pSMB);
1006 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
1007 const char *name, const struct nls_table *nls_codepage, int remap)
1010 CREATE_DIRECTORY_REQ *pSMB = NULL;
1011 CREATE_DIRECTORY_RSP *pSMBr = NULL;
1015 cFYI(1, ("In CIFSSMBMkDir"));
1017 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1022 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1023 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1024 PATH_MAX, nls_codepage, remap);
1025 name_len++; /* trailing null */
1027 } else { /* BB improve check for buffer overruns BB */
1028 name_len = strnlen(name, PATH_MAX);
1029 name_len++; /* trailing null */
1030 strncpy(pSMB->DirName, name, name_len);
1033 pSMB->BufferFormat = 0x04;
1034 pSMB->hdr.smb_buf_length += name_len + 1;
1035 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1036 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1037 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1038 cifs_stats_inc(&tcon->num_mkdirs);
1040 cFYI(1, ("Error in Mkdir = %d", rc));
1042 cifs_buf_release(pSMB);
1049 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1050 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1051 __u32 *pOplock, const char *name,
1052 const struct nls_table *nls_codepage, int remap)
1054 TRANSACTION2_SPI_REQ *pSMB = NULL;
1055 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1058 int bytes_returned = 0;
1059 __u16 params, param_offset, offset, byte_count, count;
1060 OPEN_PSX_REQ *pdata;
1061 OPEN_PSX_RSP *psx_rsp;
1063 cFYI(1, ("In POSIX Create"));
1065 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1070 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1072 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1073 PATH_MAX, nls_codepage, remap);
1074 name_len++; /* trailing null */
1076 } else { /* BB improve the check for buffer overruns BB */
1077 name_len = strnlen(name, PATH_MAX);
1078 name_len++; /* trailing null */
1079 strncpy(pSMB->FileName, name, name_len);
1082 params = 6 + name_len;
1083 count = sizeof(OPEN_PSX_REQ);
1084 pSMB->MaxParameterCount = cpu_to_le16(2);
1085 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1086 pSMB->MaxSetupCount = 0;
1090 pSMB->Reserved2 = 0;
1091 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1092 InformationLevel) - 4;
1093 offset = param_offset + params;
1094 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1095 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1096 pdata->Permissions = cpu_to_le64(mode);
1097 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1098 pdata->OpenFlags = cpu_to_le32(*pOplock);
1099 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1100 pSMB->DataOffset = cpu_to_le16(offset);
1101 pSMB->SetupCount = 1;
1102 pSMB->Reserved3 = 0;
1103 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1104 byte_count = 3 /* pad */ + params + count;
1106 pSMB->DataCount = cpu_to_le16(count);
1107 pSMB->ParameterCount = cpu_to_le16(params);
1108 pSMB->TotalDataCount = pSMB->DataCount;
1109 pSMB->TotalParameterCount = pSMB->ParameterCount;
1110 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1111 pSMB->Reserved4 = 0;
1112 pSMB->hdr.smb_buf_length += byte_count;
1113 pSMB->ByteCount = cpu_to_le16(byte_count);
1114 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1115 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1117 cFYI(1, ("Posix create returned %d", rc));
1118 goto psx_create_err;
1121 cFYI(1, ("copying inode info"));
1122 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1124 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1125 rc = -EIO; /* bad smb */
1126 goto psx_create_err;
1129 /* copy return information to pRetData */
1130 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1131 + le16_to_cpu(pSMBr->t2.DataOffset));
1133 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1135 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1136 /* Let caller know file was created so we can set the mode. */
1137 /* Do we care about the CreateAction in any other cases? */
1138 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1139 *pOplock |= CIFS_CREATE_ACTION;
1140 /* check to make sure response data is there */
1141 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1142 pRetData->Type = cpu_to_le32(-1); /* unknown */
1143 cFYI(DBG2, ("unknown type"));
1145 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1146 + sizeof(FILE_UNIX_BASIC_INFO)) {
1147 cERROR(1, ("Open response data too small"));
1148 pRetData->Type = cpu_to_le32(-1);
1149 goto psx_create_err;
1151 memcpy((char *) pRetData,
1152 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1153 sizeof(FILE_UNIX_BASIC_INFO));
1157 cifs_buf_release(pSMB);
1159 cifs_stats_inc(&tcon->num_mkdirs);
1167 static __u16 convert_disposition(int disposition)
1171 switch (disposition) {
1172 case FILE_SUPERSEDE:
1173 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1176 ofun = SMBOPEN_OAPPEND;
1179 ofun = SMBOPEN_OCREATE;
1182 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1184 case FILE_OVERWRITE:
1185 ofun = SMBOPEN_OTRUNC;
1187 case FILE_OVERWRITE_IF:
1188 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1191 cFYI(1, ("unknown disposition %d", disposition));
1192 ofun = SMBOPEN_OAPPEND; /* regular open */
1198 access_flags_to_smbopen_mode(const int access_flags)
1200 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1202 if (masked_flags == GENERIC_READ)
1203 return SMBOPEN_READ;
1204 else if (masked_flags == GENERIC_WRITE)
1205 return SMBOPEN_WRITE;
1207 /* just go for read/write */
1208 return SMBOPEN_READWRITE;
1212 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1213 const char *fileName, const int openDisposition,
1214 const int access_flags, const int create_options, __u16 *netfid,
1215 int *pOplock, FILE_ALL_INFO *pfile_info,
1216 const struct nls_table *nls_codepage, int remap)
1219 OPENX_REQ *pSMB = NULL;
1220 OPENX_RSP *pSMBr = NULL;
1226 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1231 pSMB->AndXCommand = 0xFF; /* none */
1233 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1234 count = 1; /* account for one byte pad to word boundary */
1236 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1237 fileName, PATH_MAX, nls_codepage, remap);
1238 name_len++; /* trailing null */
1240 } else { /* BB improve check for buffer overruns BB */
1241 count = 0; /* no pad */
1242 name_len = strnlen(fileName, PATH_MAX);
1243 name_len++; /* trailing null */
1244 strncpy(pSMB->fileName, fileName, name_len);
1246 if (*pOplock & REQ_OPLOCK)
1247 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1248 else if (*pOplock & REQ_BATCHOPLOCK)
1249 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1251 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1252 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1253 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1254 /* set file as system file if special file such
1255 as fifo and server expecting SFU style and
1256 no Unix extensions */
1258 if (create_options & CREATE_OPTION_SPECIAL)
1259 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1260 else /* BB FIXME BB */
1261 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1263 if (create_options & CREATE_OPTION_READONLY)
1264 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1267 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1268 CREATE_OPTIONS_MASK); */
1269 /* BB FIXME END BB */
1271 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1272 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1274 pSMB->hdr.smb_buf_length += count;
1276 pSMB->ByteCount = cpu_to_le16(count);
1277 /* long_op set to 1 to allow for oplock break timeouts */
1278 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1279 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1280 cifs_stats_inc(&tcon->num_opens);
1282 cFYI(1, ("Error in Open = %d", rc));
1284 /* BB verify if wct == 15 */
1286 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1288 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1289 /* Let caller know file was created so we can set the mode. */
1290 /* Do we care about the CreateAction in any other cases? */
1292 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1293 *pOplock |= CIFS_CREATE_ACTION; */
1297 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1298 pfile_info->LastAccessTime = 0; /* BB fixme */
1299 pfile_info->LastWriteTime = 0; /* BB fixme */
1300 pfile_info->ChangeTime = 0; /* BB fixme */
1301 pfile_info->Attributes =
1302 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1303 /* the file_info buf is endian converted by caller */
1304 pfile_info->AllocationSize =
1305 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1306 pfile_info->EndOfFile = pfile_info->AllocationSize;
1307 pfile_info->NumberOfLinks = cpu_to_le32(1);
1308 pfile_info->DeletePending = 0;
1312 cifs_buf_release(pSMB);
1319 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1320 const char *fileName, const int openDisposition,
1321 const int access_flags, const int create_options, __u16 *netfid,
1322 int *pOplock, FILE_ALL_INFO *pfile_info,
1323 const struct nls_table *nls_codepage, int remap)
1326 OPEN_REQ *pSMB = NULL;
1327 OPEN_RSP *pSMBr = NULL;
1333 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1338 pSMB->AndXCommand = 0xFF; /* none */
1340 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1341 count = 1; /* account for one byte pad to word boundary */
1343 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1344 fileName, PATH_MAX, nls_codepage, remap);
1345 name_len++; /* trailing null */
1347 pSMB->NameLength = cpu_to_le16(name_len);
1348 } else { /* BB improve check for buffer overruns BB */
1349 count = 0; /* no pad */
1350 name_len = strnlen(fileName, PATH_MAX);
1351 name_len++; /* trailing null */
1352 pSMB->NameLength = cpu_to_le16(name_len);
1353 strncpy(pSMB->fileName, fileName, name_len);
1355 if (*pOplock & REQ_OPLOCK)
1356 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1357 else if (*pOplock & REQ_BATCHOPLOCK)
1358 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1359 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1360 pSMB->AllocationSize = 0;
1361 /* set file as system file if special file such
1362 as fifo and server expecting SFU style and
1363 no Unix extensions */
1364 if (create_options & CREATE_OPTION_SPECIAL)
1365 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1367 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1369 /* XP does not handle ATTR_POSIX_SEMANTICS */
1370 /* but it helps speed up case sensitive checks for other
1371 servers such as Samba */
1372 if (tcon->ses->capabilities & CAP_UNIX)
1373 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1375 if (create_options & CREATE_OPTION_READONLY)
1376 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1378 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1379 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1380 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1381 /* BB Expirement with various impersonation levels and verify */
1382 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1383 pSMB->SecurityFlags =
1384 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1387 pSMB->hdr.smb_buf_length += count;
1389 pSMB->ByteCount = cpu_to_le16(count);
1390 /* long_op set to 1 to allow for oplock break timeouts */
1391 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1392 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1393 cifs_stats_inc(&tcon->num_opens);
1395 cFYI(1, ("Error in Open = %d", rc));
1397 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1398 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1399 /* Let caller know file was created so we can set the mode. */
1400 /* Do we care about the CreateAction in any other cases? */
1401 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1402 *pOplock |= CIFS_CREATE_ACTION;
1404 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1405 36 /* CreationTime to Attributes */);
1406 /* the file_info buf is endian converted by caller */
1407 pfile_info->AllocationSize = pSMBr->AllocationSize;
1408 pfile_info->EndOfFile = pSMBr->EndOfFile;
1409 pfile_info->NumberOfLinks = cpu_to_le32(1);
1410 pfile_info->DeletePending = 0;
1414 cifs_buf_release(pSMB);
1421 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1422 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1423 char **buf, int *pbuf_type)
1426 READ_REQ *pSMB = NULL;
1427 READ_RSP *pSMBr = NULL;
1428 char *pReadData = NULL;
1430 int resp_buf_type = 0;
1433 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1434 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1437 wct = 10; /* old style read */
1440 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1444 /* tcon and ses pointer are checked in smb_init */
1445 if (tcon->ses->server == NULL)
1446 return -ECONNABORTED;
1448 pSMB->AndXCommand = 0xFF; /* none */
1450 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1452 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1453 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1456 pSMB->Remaining = 0;
1457 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1458 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1460 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1462 /* old style read */
1463 struct smb_com_readx_req *pSMBW =
1464 (struct smb_com_readx_req *)pSMB;
1465 pSMBW->ByteCount = 0;
1468 iov[0].iov_base = (char *)pSMB;
1469 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1470 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1471 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1472 cifs_stats_inc(&tcon->num_reads);
1473 pSMBr = (READ_RSP *)iov[0].iov_base;
1475 cERROR(1, ("Send error in read = %d", rc));
1477 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1478 data_length = data_length << 16;
1479 data_length += le16_to_cpu(pSMBr->DataLength);
1480 *nbytes = data_length;
1482 /*check that DataLength would not go beyond end of SMB */
1483 if ((data_length > CIFSMaxBufSize)
1484 || (data_length > count)) {
1485 cFYI(1, ("bad length %d for count %d",
1486 data_length, count));
1490 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1491 le16_to_cpu(pSMBr->DataOffset);
1492 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1493 cERROR(1,("Faulting on read rc = %d",rc));
1495 }*/ /* can not use copy_to_user when using page cache*/
1497 memcpy(*buf, pReadData, data_length);
1501 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1503 if (resp_buf_type == CIFS_SMALL_BUFFER)
1504 cifs_small_buf_release(iov[0].iov_base);
1505 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1506 cifs_buf_release(iov[0].iov_base);
1507 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1508 /* return buffer to caller to free */
1509 *buf = iov[0].iov_base;
1510 if (resp_buf_type == CIFS_SMALL_BUFFER)
1511 *pbuf_type = CIFS_SMALL_BUFFER;
1512 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1513 *pbuf_type = CIFS_LARGE_BUFFER;
1514 } /* else no valid buffer on return - leave as null */
1516 /* Note: On -EAGAIN error only caller can retry on handle based calls
1517 since file handle passed in no longer valid */
1523 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1524 const int netfid, const unsigned int count,
1525 const __u64 offset, unsigned int *nbytes, const char *buf,
1526 const char __user *ubuf, const int long_op)
1529 WRITE_REQ *pSMB = NULL;
1530 WRITE_RSP *pSMBr = NULL;
1531 int bytes_returned, wct;
1535 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1536 if (tcon->ses == NULL)
1537 return -ECONNABORTED;
1539 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1544 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1548 /* tcon and ses pointer are checked in smb_init */
1549 if (tcon->ses->server == NULL)
1550 return -ECONNABORTED;
1552 pSMB->AndXCommand = 0xFF; /* none */
1554 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1556 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1557 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1560 pSMB->Reserved = 0xFFFFFFFF;
1561 pSMB->WriteMode = 0;
1562 pSMB->Remaining = 0;
1564 /* Can increase buffer size if buffer is big enough in some cases ie we
1565 can send more if LARGE_WRITE_X capability returned by the server and if
1566 our buffer is big enough or if we convert to iovecs on socket writes
1567 and eliminate the copy to the CIFS buffer */
1568 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1569 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1571 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1575 if (bytes_sent > count)
1578 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1580 memcpy(pSMB->Data, buf, bytes_sent);
1582 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1583 cifs_buf_release(pSMB);
1586 } else if (count != 0) {
1588 cifs_buf_release(pSMB);
1590 } /* else setting file size with write of zero bytes */
1592 byte_count = bytes_sent + 1; /* pad */
1593 else /* wct == 12 */
1594 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1596 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1597 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1598 pSMB->hdr.smb_buf_length += byte_count;
1601 pSMB->ByteCount = cpu_to_le16(byte_count);
1602 else { /* old style write has byte count 4 bytes earlier
1604 struct smb_com_writex_req *pSMBW =
1605 (struct smb_com_writex_req *)pSMB;
1606 pSMBW->ByteCount = cpu_to_le16(byte_count);
1609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1610 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1611 cifs_stats_inc(&tcon->num_writes);
1613 cFYI(1, ("Send error in write = %d", rc));
1616 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1617 *nbytes = (*nbytes) << 16;
1618 *nbytes += le16_to_cpu(pSMBr->Count);
1621 cifs_buf_release(pSMB);
1623 /* Note: On -EAGAIN error only caller can retry on handle based calls
1624 since file handle passed in no longer valid */
1630 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1631 const int netfid, const unsigned int count,
1632 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1633 int n_vec, const int long_op)
1636 WRITE_REQ *pSMB = NULL;
1639 int resp_buf_type = 0;
1641 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1643 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1647 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1650 /* tcon and ses pointer are checked in smb_init */
1651 if (tcon->ses->server == NULL)
1652 return -ECONNABORTED;
1654 pSMB->AndXCommand = 0xFF; /* none */
1656 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1658 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1659 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1661 pSMB->Reserved = 0xFFFFFFFF;
1662 pSMB->WriteMode = 0;
1663 pSMB->Remaining = 0;
1666 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1668 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1669 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1670 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1672 pSMB->hdr.smb_buf_length += count+1;
1673 else /* wct == 12 */
1674 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1676 pSMB->ByteCount = cpu_to_le16(count + 1);
1677 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1678 struct smb_com_writex_req *pSMBW =
1679 (struct smb_com_writex_req *)pSMB;
1680 pSMBW->ByteCount = cpu_to_le16(count + 5);
1682 iov[0].iov_base = pSMB;
1684 iov[0].iov_len = smb_hdr_len + 4;
1685 else /* wct == 12 pad bigger by four bytes */
1686 iov[0].iov_len = smb_hdr_len + 8;
1689 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1691 cifs_stats_inc(&tcon->num_writes);
1693 cFYI(1, ("Send error Write2 = %d", rc));
1695 } else if (resp_buf_type == 0) {
1696 /* presumably this can not happen, but best to be safe */
1700 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1701 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1702 *nbytes = (*nbytes) << 16;
1703 *nbytes += le16_to_cpu(pSMBr->Count);
1706 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1707 if (resp_buf_type == CIFS_SMALL_BUFFER)
1708 cifs_small_buf_release(iov[0].iov_base);
1709 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1710 cifs_buf_release(iov[0].iov_base);
1712 /* Note: On -EAGAIN error only caller can retry on handle based calls
1713 since file handle passed in no longer valid */
1720 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1721 const __u16 smb_file_id, const __u64 len,
1722 const __u64 offset, const __u32 numUnlock,
1723 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1726 LOCK_REQ *pSMB = NULL;
1727 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1732 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1733 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1738 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1739 timeout = CIFS_ASYNC_OP; /* no response expected */
1741 } else if (waitFlag) {
1742 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1743 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1748 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1749 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1750 pSMB->LockType = lockType;
1751 pSMB->AndXCommand = 0xFF; /* none */
1752 pSMB->Fid = smb_file_id; /* netfid stays le */
1754 if ((numLock != 0) || (numUnlock != 0)) {
1755 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1756 /* BB where to store pid high? */
1757 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1758 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1759 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1760 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1761 count = sizeof(LOCKING_ANDX_RANGE);
1766 pSMB->hdr.smb_buf_length += count;
1767 pSMB->ByteCount = cpu_to_le16(count);
1770 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1771 (struct smb_hdr *) pSMB, &bytes_returned);
1772 cifs_small_buf_release(pSMB);
1774 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1776 /* SMB buffer freed by function above */
1778 cifs_stats_inc(&tcon->num_locks);
1780 cFYI(1, ("Send error in Lock = %d", rc));
1782 /* Note: On -EAGAIN error only caller can retry on handle based calls
1783 since file handle passed in no longer valid */
1788 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1789 const __u16 smb_file_id, const int get_flag, const __u64 len,
1790 struct file_lock *pLockData, const __u16 lock_type,
1791 const bool waitFlag)
1793 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1794 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1795 struct cifs_posix_lock *parm_data;
1798 int bytes_returned = 0;
1799 int resp_buf_type = 0;
1800 __u16 params, param_offset, offset, byte_count, count;
1803 cFYI(1, ("Posix Lock"));
1805 if (pLockData == NULL)
1808 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1813 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1816 pSMB->MaxSetupCount = 0;
1819 pSMB->Reserved2 = 0;
1820 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1821 offset = param_offset + params;
1823 count = sizeof(struct cifs_posix_lock);
1824 pSMB->MaxParameterCount = cpu_to_le16(2);
1825 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1826 pSMB->SetupCount = 1;
1827 pSMB->Reserved3 = 0;
1829 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1831 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1832 byte_count = 3 /* pad */ + params + count;
1833 pSMB->DataCount = cpu_to_le16(count);
1834 pSMB->ParameterCount = cpu_to_le16(params);
1835 pSMB->TotalDataCount = pSMB->DataCount;
1836 pSMB->TotalParameterCount = pSMB->ParameterCount;
1837 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1838 parm_data = (struct cifs_posix_lock *)
1839 (((char *) &pSMB->hdr.Protocol) + offset);
1841 parm_data->lock_type = cpu_to_le16(lock_type);
1843 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1844 parm_data->lock_flags = cpu_to_le16(1);
1845 pSMB->Timeout = cpu_to_le32(-1);
1849 parm_data->pid = cpu_to_le32(current->tgid);
1850 parm_data->start = cpu_to_le64(pLockData->fl_start);
1851 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1853 pSMB->DataOffset = cpu_to_le16(offset);
1854 pSMB->Fid = smb_file_id;
1855 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1856 pSMB->Reserved4 = 0;
1857 pSMB->hdr.smb_buf_length += byte_count;
1858 pSMB->ByteCount = cpu_to_le16(byte_count);
1860 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1861 (struct smb_hdr *) pSMBr, &bytes_returned);
1863 iov[0].iov_base = (char *)pSMB;
1864 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1865 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1866 &resp_buf_type, timeout);
1867 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1868 not try to free it twice below on exit */
1869 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1873 cFYI(1, ("Send error in Posix Lock = %d", rc));
1874 } else if (get_flag) {
1875 /* lock structure can be returned on get */
1878 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1880 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1881 rc = -EIO; /* bad smb */
1884 if (pLockData == NULL) {
1888 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1889 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1890 if (data_count < sizeof(struct cifs_posix_lock)) {
1894 parm_data = (struct cifs_posix_lock *)
1895 ((char *)&pSMBr->hdr.Protocol + data_offset);
1896 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1897 pLockData->fl_type = F_UNLCK;
1902 cifs_small_buf_release(pSMB);
1904 if (resp_buf_type == CIFS_SMALL_BUFFER)
1905 cifs_small_buf_release(iov[0].iov_base);
1906 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1907 cifs_buf_release(iov[0].iov_base);
1909 /* Note: On -EAGAIN error only caller can retry on handle based calls
1910 since file handle passed in no longer valid */
1917 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1920 CLOSE_REQ *pSMB = NULL;
1921 cFYI(1, ("In CIFSSMBClose"));
1923 /* do not retry on dead session on close */
1924 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1930 pSMB->FileID = (__u16) smb_file_id;
1931 pSMB->LastWriteTime = 0xFFFFFFFF;
1932 pSMB->ByteCount = 0;
1933 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1934 cifs_stats_inc(&tcon->num_closes);
1937 /* EINTR is expected when user ctl-c to kill app */
1938 cERROR(1, ("Send error in Close = %d", rc));
1942 /* Since session is dead, file will be closed on server already */
1950 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1951 const char *fromName, const char *toName,
1952 const struct nls_table *nls_codepage, int remap)
1955 RENAME_REQ *pSMB = NULL;
1956 RENAME_RSP *pSMBr = NULL;
1958 int name_len, name_len2;
1961 cFYI(1, ("In CIFSSMBRename"));
1963 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1968 pSMB->BufferFormat = 0x04;
1969 pSMB->SearchAttributes =
1970 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1973 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1975 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1976 PATH_MAX, nls_codepage, remap);
1977 name_len++; /* trailing null */
1979 pSMB->OldFileName[name_len] = 0x04; /* pad */
1980 /* protocol requires ASCII signature byte on Unicode string */
1981 pSMB->OldFileName[name_len + 1] = 0x00;
1983 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1984 toName, PATH_MAX, nls_codepage, remap);
1985 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1986 name_len2 *= 2; /* convert to bytes */
1987 } else { /* BB improve the check for buffer overruns BB */
1988 name_len = strnlen(fromName, PATH_MAX);
1989 name_len++; /* trailing null */
1990 strncpy(pSMB->OldFileName, fromName, name_len);
1991 name_len2 = strnlen(toName, PATH_MAX);
1992 name_len2++; /* trailing null */
1993 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1994 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1995 name_len2++; /* trailing null */
1996 name_len2++; /* signature byte */
1999 count = 1 /* 1st signature byte */ + name_len + name_len2;
2000 pSMB->hdr.smb_buf_length += count;
2001 pSMB->ByteCount = cpu_to_le16(count);
2003 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2004 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2005 cifs_stats_inc(&tcon->num_renames);
2007 cFYI(1, ("Send error in rename = %d", rc));
2009 cifs_buf_release(pSMB);
2017 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2018 int netfid, const char *target_name,
2019 const struct nls_table *nls_codepage, int remap)
2021 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2022 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2023 struct set_file_rename *rename_info;
2025 char dummy_string[30];
2027 int bytes_returned = 0;
2029 __u16 params, param_offset, offset, count, byte_count;
2031 cFYI(1, ("Rename to File by handle"));
2032 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2038 pSMB->MaxSetupCount = 0;
2042 pSMB->Reserved2 = 0;
2043 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2044 offset = param_offset + params;
2046 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2047 rename_info = (struct set_file_rename *) data_offset;
2048 pSMB->MaxParameterCount = cpu_to_le16(2);
2049 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2050 pSMB->SetupCount = 1;
2051 pSMB->Reserved3 = 0;
2052 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2053 byte_count = 3 /* pad */ + params;
2054 pSMB->ParameterCount = cpu_to_le16(params);
2055 pSMB->TotalParameterCount = pSMB->ParameterCount;
2056 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2057 pSMB->DataOffset = cpu_to_le16(offset);
2058 /* construct random name ".cifs_tmp<inodenum><mid>" */
2059 rename_info->overwrite = cpu_to_le32(1);
2060 rename_info->root_fid = 0;
2061 /* unicode only call */
2062 if (target_name == NULL) {
2063 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2064 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2065 dummy_string, 24, nls_codepage, remap);
2067 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2068 target_name, PATH_MAX, nls_codepage,
2071 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2072 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2073 byte_count += count;
2074 pSMB->DataCount = cpu_to_le16(count);
2075 pSMB->TotalDataCount = pSMB->DataCount;
2077 pSMB->InformationLevel =
2078 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2079 pSMB->Reserved4 = 0;
2080 pSMB->hdr.smb_buf_length += byte_count;
2081 pSMB->ByteCount = cpu_to_le16(byte_count);
2082 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2083 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2084 cifs_stats_inc(&pTcon->num_t2renames);
2086 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2088 cifs_buf_release(pSMB);
2090 /* Note: On -EAGAIN error only caller can retry on handle based calls
2091 since file handle passed in no longer valid */
2097 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2098 const __u16 target_tid, const char *toName, const int flags,
2099 const struct nls_table *nls_codepage, int remap)
2102 COPY_REQ *pSMB = NULL;
2103 COPY_RSP *pSMBr = NULL;
2105 int name_len, name_len2;
2108 cFYI(1, ("In CIFSSMBCopy"));
2110 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2115 pSMB->BufferFormat = 0x04;
2116 pSMB->Tid2 = target_tid;
2118 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2120 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2121 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2122 fromName, PATH_MAX, nls_codepage,
2124 name_len++; /* trailing null */
2126 pSMB->OldFileName[name_len] = 0x04; /* pad */
2127 /* protocol requires ASCII signature byte on Unicode string */
2128 pSMB->OldFileName[name_len + 1] = 0x00;
2130 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2131 toName, PATH_MAX, nls_codepage, remap);
2132 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2133 name_len2 *= 2; /* convert to bytes */
2134 } else { /* BB improve the check for buffer overruns BB */
2135 name_len = strnlen(fromName, PATH_MAX);
2136 name_len++; /* trailing null */
2137 strncpy(pSMB->OldFileName, fromName, name_len);
2138 name_len2 = strnlen(toName, PATH_MAX);
2139 name_len2++; /* trailing null */
2140 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2141 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2142 name_len2++; /* trailing null */
2143 name_len2++; /* signature byte */
2146 count = 1 /* 1st signature byte */ + name_len + name_len2;
2147 pSMB->hdr.smb_buf_length += count;
2148 pSMB->ByteCount = cpu_to_le16(count);
2150 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2151 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2153 cFYI(1, ("Send error in copy = %d with %d files copied",
2154 rc, le16_to_cpu(pSMBr->CopyCount)));
2156 cifs_buf_release(pSMB);
2165 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2166 const char *fromName, const char *toName,
2167 const struct nls_table *nls_codepage)
2169 TRANSACTION2_SPI_REQ *pSMB = NULL;
2170 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2173 int name_len_target;
2175 int bytes_returned = 0;
2176 __u16 params, param_offset, offset, byte_count;
2178 cFYI(1, ("In Symlink Unix style"));
2180 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2185 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2187 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2188 /* find define for this maxpathcomponent */
2190 name_len++; /* trailing null */
2193 } else { /* BB improve the check for buffer overruns BB */
2194 name_len = strnlen(fromName, PATH_MAX);
2195 name_len++; /* trailing null */
2196 strncpy(pSMB->FileName, fromName, name_len);
2198 params = 6 + name_len;
2199 pSMB->MaxSetupCount = 0;
2203 pSMB->Reserved2 = 0;
2204 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2205 InformationLevel) - 4;
2206 offset = param_offset + params;
2208 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2209 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2211 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2212 /* find define for this maxpathcomponent */
2214 name_len_target++; /* trailing null */
2215 name_len_target *= 2;
2216 } else { /* BB improve the check for buffer overruns BB */
2217 name_len_target = strnlen(toName, PATH_MAX);
2218 name_len_target++; /* trailing null */
2219 strncpy(data_offset, toName, name_len_target);
2222 pSMB->MaxParameterCount = cpu_to_le16(2);
2223 /* BB find exact max on data count below from sess */
2224 pSMB->MaxDataCount = cpu_to_le16(1000);
2225 pSMB->SetupCount = 1;
2226 pSMB->Reserved3 = 0;
2227 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2228 byte_count = 3 /* pad */ + params + name_len_target;
2229 pSMB->DataCount = cpu_to_le16(name_len_target);
2230 pSMB->ParameterCount = cpu_to_le16(params);
2231 pSMB->TotalDataCount = pSMB->DataCount;
2232 pSMB->TotalParameterCount = pSMB->ParameterCount;
2233 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2234 pSMB->DataOffset = cpu_to_le16(offset);
2235 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2236 pSMB->Reserved4 = 0;
2237 pSMB->hdr.smb_buf_length += byte_count;
2238 pSMB->ByteCount = cpu_to_le16(byte_count);
2239 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2240 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2241 cifs_stats_inc(&tcon->num_symlinks);
2243 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2245 cifs_buf_release(pSMB);
2248 goto createSymLinkRetry;
2254 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2255 const char *fromName, const char *toName,
2256 const struct nls_table *nls_codepage, int remap)
2258 TRANSACTION2_SPI_REQ *pSMB = NULL;
2259 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2262 int name_len_target;
2264 int bytes_returned = 0;
2265 __u16 params, param_offset, offset, byte_count;
2267 cFYI(1, ("In Create Hard link Unix style"));
2268 createHardLinkRetry:
2269 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2274 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2275 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2276 PATH_MAX, nls_codepage, remap);
2277 name_len++; /* trailing null */
2280 } else { /* BB improve the check for buffer overruns BB */
2281 name_len = strnlen(toName, PATH_MAX);
2282 name_len++; /* trailing null */
2283 strncpy(pSMB->FileName, toName, name_len);
2285 params = 6 + name_len;
2286 pSMB->MaxSetupCount = 0;
2290 pSMB->Reserved2 = 0;
2291 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2292 InformationLevel) - 4;
2293 offset = param_offset + params;
2295 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2296 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2298 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2299 nls_codepage, remap);
2300 name_len_target++; /* trailing null */
2301 name_len_target *= 2;
2302 } else { /* BB improve the check for buffer overruns BB */
2303 name_len_target = strnlen(fromName, PATH_MAX);
2304 name_len_target++; /* trailing null */
2305 strncpy(data_offset, fromName, name_len_target);
2308 pSMB->MaxParameterCount = cpu_to_le16(2);
2309 /* BB find exact max on data count below from sess*/
2310 pSMB->MaxDataCount = cpu_to_le16(1000);
2311 pSMB->SetupCount = 1;
2312 pSMB->Reserved3 = 0;
2313 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2314 byte_count = 3 /* pad */ + params + name_len_target;
2315 pSMB->ParameterCount = cpu_to_le16(params);
2316 pSMB->TotalParameterCount = pSMB->ParameterCount;
2317 pSMB->DataCount = cpu_to_le16(name_len_target);
2318 pSMB->TotalDataCount = pSMB->DataCount;
2319 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2320 pSMB->DataOffset = cpu_to_le16(offset);
2321 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2322 pSMB->Reserved4 = 0;
2323 pSMB->hdr.smb_buf_length += byte_count;
2324 pSMB->ByteCount = cpu_to_le16(byte_count);
2325 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2326 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2327 cifs_stats_inc(&tcon->num_hardlinks);
2329 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2331 cifs_buf_release(pSMB);
2333 goto createHardLinkRetry;
2339 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2340 const char *fromName, const char *toName,
2341 const struct nls_table *nls_codepage, int remap)
2344 NT_RENAME_REQ *pSMB = NULL;
2345 RENAME_RSP *pSMBr = NULL;
2347 int name_len, name_len2;
2350 cFYI(1, ("In CIFSCreateHardLink"));
2351 winCreateHardLinkRetry:
2353 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2358 pSMB->SearchAttributes =
2359 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2361 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2362 pSMB->ClusterCount = 0;
2364 pSMB->BufferFormat = 0x04;
2366 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2368 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2369 PATH_MAX, nls_codepage, remap);
2370 name_len++; /* trailing null */
2372 pSMB->OldFileName[name_len] = 0; /* pad */
2373 pSMB->OldFileName[name_len + 1] = 0x04;
2375 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2376 toName, PATH_MAX, nls_codepage, remap);
2377 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2378 name_len2 *= 2; /* convert to bytes */
2379 } else { /* BB improve the check for buffer overruns BB */
2380 name_len = strnlen(fromName, PATH_MAX);
2381 name_len++; /* trailing null */
2382 strncpy(pSMB->OldFileName, fromName, name_len);
2383 name_len2 = strnlen(toName, PATH_MAX);
2384 name_len2++; /* trailing null */
2385 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2386 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2387 name_len2++; /* trailing null */
2388 name_len2++; /* signature byte */
2391 count = 1 /* string type byte */ + name_len + name_len2;
2392 pSMB->hdr.smb_buf_length += count;
2393 pSMB->ByteCount = cpu_to_le16(count);
2395 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2396 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2397 cifs_stats_inc(&tcon->num_hardlinks);
2399 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2401 cifs_buf_release(pSMB);
2403 goto winCreateHardLinkRetry;
2409 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2410 const unsigned char *searchName,
2411 char *symlinkinfo, const int buflen,
2412 const struct nls_table *nls_codepage)
2414 /* SMB_QUERY_FILE_UNIX_LINK */
2415 TRANSACTION2_QPI_REQ *pSMB = NULL;
2416 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2420 __u16 params, byte_count;
2422 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2425 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2430 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2432 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2433 PATH_MAX, nls_codepage);
2434 name_len++; /* trailing null */
2436 } else { /* BB improve the check for buffer overruns BB */
2437 name_len = strnlen(searchName, PATH_MAX);
2438 name_len++; /* trailing null */
2439 strncpy(pSMB->FileName, searchName, name_len);
2442 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2443 pSMB->TotalDataCount = 0;
2444 pSMB->MaxParameterCount = cpu_to_le16(2);
2445 /* BB find exact max data count below from sess structure BB */
2446 pSMB->MaxDataCount = cpu_to_le16(4000);
2447 pSMB->MaxSetupCount = 0;
2451 pSMB->Reserved2 = 0;
2452 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2453 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2454 pSMB->DataCount = 0;
2455 pSMB->DataOffset = 0;
2456 pSMB->SetupCount = 1;
2457 pSMB->Reserved3 = 0;
2458 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2459 byte_count = params + 1 /* pad */ ;
2460 pSMB->TotalParameterCount = cpu_to_le16(params);
2461 pSMB->ParameterCount = pSMB->TotalParameterCount;
2462 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2463 pSMB->Reserved4 = 0;
2464 pSMB->hdr.smb_buf_length += byte_count;
2465 pSMB->ByteCount = cpu_to_le16(byte_count);
2467 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2468 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2470 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2472 /* decode response */
2474 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2475 if (rc || (pSMBr->ByteCount < 2))
2476 /* BB also check enough total bytes returned */
2477 rc = -EIO; /* bad smb */
2479 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2480 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2482 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2483 name_len = UniStrnlen((wchar_t *) ((char *)
2484 &pSMBr->hdr.Protocol + data_offset),
2485 min_t(const int, buflen, count) / 2);
2486 /* BB FIXME investigate remapping reserved chars here */
2487 cifs_strfromUCS_le(symlinkinfo,
2488 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2490 name_len, nls_codepage);
2492 strncpy(symlinkinfo,
2493 (char *) &pSMBr->hdr.Protocol +
2495 min_t(const int, buflen, count));
2497 symlinkinfo[buflen] = 0;
2498 /* just in case so calling code does not go off the end of buffer */
2501 cifs_buf_release(pSMB);
2503 goto querySymLinkRetry;
2507 #ifdef CONFIG_CIFS_EXPERIMENTAL
2508 /* Initialize NT TRANSACT SMB into small smb request buffer.
2509 This assumes that all NT TRANSACTS that we init here have
2510 total parm and data under about 400 bytes (to fit in small cifs
2511 buffer size), which is the case so far, it easily fits. NB:
2512 Setup words themselves and ByteCount
2513 MaxSetupCount (size of returned setup area) and
2514 MaxParameterCount (returned parms size) must be set by caller */
2516 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2517 const int parm_len, struct cifsTconInfo *tcon,
2522 struct smb_com_ntransact_req *pSMB;
2524 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2528 *ret_buf = (void *)pSMB;
2530 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2531 pSMB->TotalDataCount = 0;
2532 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2533 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2534 pSMB->ParameterCount = pSMB->TotalParameterCount;
2535 pSMB->DataCount = pSMB->TotalDataCount;
2536 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2537 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2538 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2539 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2540 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2541 pSMB->SubCommand = cpu_to_le16(sub_command);
2546 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2547 __u32 *pparmlen, __u32 *pdatalen)
2550 __u32 data_count, data_offset, parm_count, parm_offset;
2551 struct smb_com_ntransact_rsp *pSMBr;
2559 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2561 /* ByteCount was converted from little endian in SendReceive */
2562 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2563 (char *)&pSMBr->ByteCount;
2565 data_offset = le32_to_cpu(pSMBr->DataOffset);
2566 data_count = le32_to_cpu(pSMBr->DataCount);
2567 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2568 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2570 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2571 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2573 /* should we also check that parm and data areas do not overlap? */
2574 if (*ppparm > end_of_smb) {
2575 cFYI(1, ("parms start after end of smb"));
2577 } else if (parm_count + *ppparm > end_of_smb) {
2578 cFYI(1, ("parm end after end of smb"));
2580 } else if (*ppdata > end_of_smb) {
2581 cFYI(1, ("data starts after end of smb"));
2583 } else if (data_count + *ppdata > end_of_smb) {
2584 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2585 *ppdata, data_count, (data_count + *ppdata),
2586 end_of_smb, pSMBr));
2588 } else if (parm_count + data_count > pSMBr->ByteCount) {
2589 cFYI(1, ("parm count and data count larger than SMB"));
2592 *pdatalen = data_count;
2593 *pparmlen = parm_count;
2596 #endif /* CIFS_EXPERIMENTAL */
2599 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2600 const unsigned char *searchName,
2601 char *symlinkinfo, const int buflen, __u16 fid,
2602 const struct nls_table *nls_codepage)
2607 struct smb_com_transaction_ioctl_req *pSMB;
2608 struct smb_com_transaction_ioctl_rsp *pSMBr;
2610 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2611 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2616 pSMB->TotalParameterCount = 0 ;
2617 pSMB->TotalDataCount = 0;
2618 pSMB->MaxParameterCount = cpu_to_le32(2);
2619 /* BB find exact data count max from sess structure BB */
2620 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2621 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2622 pSMB->MaxSetupCount = 4;
2624 pSMB->ParameterOffset = 0;
2625 pSMB->DataCount = 0;
2626 pSMB->DataOffset = 0;
2627 pSMB->SetupCount = 4;
2628 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2629 pSMB->ParameterCount = pSMB->TotalParameterCount;
2630 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2631 pSMB->IsFsctl = 1; /* FSCTL */
2632 pSMB->IsRootFlag = 0;
2633 pSMB->Fid = fid; /* file handle always le */
2634 pSMB->ByteCount = 0;
2636 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2637 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2639 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2640 } else { /* decode response */
2641 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2642 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2643 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2644 /* BB also check enough total bytes returned */
2645 rc = -EIO; /* bad smb */
2647 if (data_count && (data_count < 2048)) {
2648 char *end_of_smb = 2 /* sizeof byte count */ +
2650 (char *)&pSMBr->ByteCount;
2652 struct reparse_data *reparse_buf =
2653 (struct reparse_data *)
2654 ((char *)&pSMBr->hdr.Protocol
2656 if ((char *)reparse_buf >= end_of_smb) {
2660 if ((reparse_buf->LinkNamesBuf +
2661 reparse_buf->TargetNameOffset +
2662 reparse_buf->TargetNameLen) >
2664 cFYI(1, ("reparse buf beyond SMB"));
2669 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2670 name_len = UniStrnlen((wchar_t *)
2671 (reparse_buf->LinkNamesBuf +
2672 reparse_buf->TargetNameOffset),
2674 reparse_buf->TargetNameLen / 2));
2675 cifs_strfromUCS_le(symlinkinfo,
2676 (__le16 *) (reparse_buf->LinkNamesBuf +
2677 reparse_buf->TargetNameOffset),
2678 name_len, nls_codepage);
2679 } else { /* ASCII names */
2680 strncpy(symlinkinfo,
2681 reparse_buf->LinkNamesBuf +
2682 reparse_buf->TargetNameOffset,
2683 min_t(const int, buflen,
2684 reparse_buf->TargetNameLen));
2688 cFYI(1, ("Invalid return data count on "
2689 "get reparse info ioctl"));
2691 symlinkinfo[buflen] = 0; /* just in case so the caller
2692 does not go off the end of the buffer */
2693 cFYI(1, ("readlink result - %s", symlinkinfo));
2697 cifs_buf_release(pSMB);
2699 /* Note: On -EAGAIN error only caller can retry on handle based calls
2700 since file handle passed in no longer valid */
2705 #ifdef CONFIG_CIFS_POSIX
2707 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2708 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2709 struct cifs_posix_ace *cifs_ace)
2711 /* u8 cifs fields do not need le conversion */
2712 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2713 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2714 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2715 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2720 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2721 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2722 const int acl_type, const int size_of_data_area)
2727 struct cifs_posix_ace *pACE;
2728 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2729 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2731 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2734 if (acl_type & ACL_TYPE_ACCESS) {
2735 count = le16_to_cpu(cifs_acl->access_entry_count);
2736 pACE = &cifs_acl->ace_array[0];
2737 size = sizeof(struct cifs_posix_acl);
2738 size += sizeof(struct cifs_posix_ace) * count;
2739 /* check if we would go beyond end of SMB */
2740 if (size_of_data_area < size) {
2741 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2742 size_of_data_area, size));
2745 } else if (acl_type & ACL_TYPE_DEFAULT) {
2746 count = le16_to_cpu(cifs_acl->access_entry_count);
2747 size = sizeof(struct cifs_posix_acl);
2748 size += sizeof(struct cifs_posix_ace) * count;
2749 /* skip past access ACEs to get to default ACEs */
2750 pACE = &cifs_acl->ace_array[count];
2751 count = le16_to_cpu(cifs_acl->default_entry_count);
2752 size += sizeof(struct cifs_posix_ace) * count;
2753 /* check if we would go beyond end of SMB */
2754 if (size_of_data_area < size)
2761 size = posix_acl_xattr_size(count);
2762 if ((buflen == 0) || (local_acl == NULL)) {
2763 /* used to query ACL EA size */
2764 } else if (size > buflen) {
2766 } else /* buffer big enough */ {
2767 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2768 for (i = 0; i < count ; i++) {
2769 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2776 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2777 const posix_acl_xattr_entry *local_ace)
2779 __u16 rc = 0; /* 0 = ACL converted ok */
2781 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2782 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2783 /* BB is there a better way to handle the large uid? */
2784 if (local_ace->e_id == cpu_to_le32(-1)) {
2785 /* Probably no need to le convert -1 on any arch but can not hurt */
2786 cifs_ace->cifs_uid = cpu_to_le64(-1);
2788 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2789 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2793 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2794 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2795 const int buflen, const int acl_type)
2798 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2799 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2803 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2806 count = posix_acl_xattr_count((size_t)buflen);
2807 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2809 count, buflen, le32_to_cpu(local_acl->a_version)));
2810 if (le32_to_cpu(local_acl->a_version) != 2) {
2811 cFYI(1, ("unknown POSIX ACL version %d",
2812 le32_to_cpu(local_acl->a_version)));
2815 cifs_acl->version = cpu_to_le16(1);
2816 if (acl_type == ACL_TYPE_ACCESS)
2817 cifs_acl->access_entry_count = cpu_to_le16(count);
2818 else if (acl_type == ACL_TYPE_DEFAULT)
2819 cifs_acl->default_entry_count = cpu_to_le16(count);
2821 cFYI(1, ("unknown ACL type %d", acl_type));
2824 for (i = 0; i < count; i++) {
2825 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2826 &local_acl->a_entries[i]);
2828 /* ACE not converted */
2833 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2834 rc += sizeof(struct cifs_posix_acl);
2835 /* BB add check to make sure ACL does not overflow SMB */
2841 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2842 const unsigned char *searchName,
2843 char *acl_inf, const int buflen, const int acl_type,
2844 const struct nls_table *nls_codepage, int remap)
2846 /* SMB_QUERY_POSIX_ACL */
2847 TRANSACTION2_QPI_REQ *pSMB = NULL;
2848 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2852 __u16 params, byte_count;
2854 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2857 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2862 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2864 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2865 PATH_MAX, nls_codepage, remap);
2866 name_len++; /* trailing null */
2868 pSMB->FileName[name_len] = 0;
2869 pSMB->FileName[name_len+1] = 0;
2870 } else { /* BB improve the check for buffer overruns BB */
2871 name_len = strnlen(searchName, PATH_MAX);
2872 name_len++; /* trailing null */
2873 strncpy(pSMB->FileName, searchName, name_len);
2876 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2877 pSMB->TotalDataCount = 0;
2878 pSMB->MaxParameterCount = cpu_to_le16(2);
2879 /* BB find exact max data count below from sess structure BB */
2880 pSMB->MaxDataCount = cpu_to_le16(4000);
2881 pSMB->MaxSetupCount = 0;
2885 pSMB->Reserved2 = 0;
2886 pSMB->ParameterOffset = cpu_to_le16(
2887 offsetof(struct smb_com_transaction2_qpi_req,
2888 InformationLevel) - 4);
2889 pSMB->DataCount = 0;
2890 pSMB->DataOffset = 0;
2891 pSMB->SetupCount = 1;
2892 pSMB->Reserved3 = 0;
2893 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2894 byte_count = params + 1 /* pad */ ;
2895 pSMB->TotalParameterCount = cpu_to_le16(params);
2896 pSMB->ParameterCount = pSMB->TotalParameterCount;
2897 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2898 pSMB->Reserved4 = 0;
2899 pSMB->hdr.smb_buf_length += byte_count;
2900 pSMB->ByteCount = cpu_to_le16(byte_count);
2902 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2903 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2904 cifs_stats_inc(&tcon->num_acl_get);
2906 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2908 /* decode response */
2910 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2911 if (rc || (pSMBr->ByteCount < 2))
2912 /* BB also check enough total bytes returned */
2913 rc = -EIO; /* bad smb */
2915 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2916 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2917 rc = cifs_copy_posix_acl(acl_inf,
2918 (char *)&pSMBr->hdr.Protocol+data_offset,
2919 buflen, acl_type, count);
2922 cifs_buf_release(pSMB);
2929 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2930 const unsigned char *fileName,
2931 const char *local_acl, const int buflen,
2933 const struct nls_table *nls_codepage, int remap)
2935 struct smb_com_transaction2_spi_req *pSMB = NULL;
2936 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2940 int bytes_returned = 0;
2941 __u16 params, byte_count, data_count, param_offset, offset;
2943 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2945 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2951 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2952 PATH_MAX, nls_codepage, remap);
2953 name_len++; /* trailing null */
2955 } else { /* BB improve the check for buffer overruns BB */
2956 name_len = strnlen(fileName, PATH_MAX);
2957 name_len++; /* trailing null */
2958 strncpy(pSMB->FileName, fileName, name_len);
2960 params = 6 + name_len;
2961 pSMB->MaxParameterCount = cpu_to_le16(2);
2962 /* BB find max SMB size from sess */
2963 pSMB->MaxDataCount = cpu_to_le16(1000);
2964 pSMB->MaxSetupCount = 0;
2968 pSMB->Reserved2 = 0;
2969 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2970 InformationLevel) - 4;
2971 offset = param_offset + params;
2972 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2973 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2975 /* convert to on the wire format for POSIX ACL */
2976 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2978 if (data_count == 0) {
2980 goto setACLerrorExit;
2982 pSMB->DataOffset = cpu_to_le16(offset);
2983 pSMB->SetupCount = 1;
2984 pSMB->Reserved3 = 0;
2985 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2986 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2987 byte_count = 3 /* pad */ + params + data_count;
2988 pSMB->DataCount = cpu_to_le16(data_count);
2989 pSMB->TotalDataCount = pSMB->DataCount;
2990 pSMB->ParameterCount = cpu_to_le16(params);
2991 pSMB->TotalParameterCount = pSMB->ParameterCount;
2992 pSMB->Reserved4 = 0;
2993 pSMB->hdr.smb_buf_length += byte_count;
2994 pSMB->ByteCount = cpu_to_le16(byte_count);
2995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2998 cFYI(1, ("Set POSIX ACL returned %d", rc));
3001 cifs_buf_release(pSMB);
3007 /* BB fix tabs in this function FIXME BB */
3009 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3010 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3013 struct smb_t2_qfi_req *pSMB = NULL;
3014 struct smb_t2_qfi_rsp *pSMBr = NULL;
3016 __u16 params, byte_count;
3018 cFYI(1, ("In GetExtAttr"));
3023 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3028 params = 2 /* level */ + 2 /* fid */;
3029 pSMB->t2.TotalDataCount = 0;
3030 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3031 /* BB find exact max data count below from sess structure BB */
3032 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3033 pSMB->t2.MaxSetupCount = 0;
3034 pSMB->t2.Reserved = 0;
3036 pSMB->t2.Timeout = 0;
3037 pSMB->t2.Reserved2 = 0;
3038 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3040 pSMB->t2.DataCount = 0;
3041 pSMB->t2.DataOffset = 0;
3042 pSMB->t2.SetupCount = 1;
3043 pSMB->t2.Reserved3 = 0;
3044 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3045 byte_count = params + 1 /* pad */ ;
3046 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3047 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3048 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3051 pSMB->hdr.smb_buf_length += byte_count;
3052 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3054 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3055 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3057 cFYI(1, ("error %d in GetExtAttr", rc));
3059 /* decode response */
3060 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3061 if (rc || (pSMBr->ByteCount < 2))
3062 /* BB also check enough total bytes returned */
3063 /* If rc should we check for EOPNOSUPP and
3064 disable the srvino flag? or in caller? */
3065 rc = -EIO; /* bad smb */
3067 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3068 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3069 struct file_chattr_info *pfinfo;
3070 /* BB Do we need a cast or hash here ? */
3072 cFYI(1, ("Illegal size ret in GetExtAttr"));
3076 pfinfo = (struct file_chattr_info *)
3077 (data_offset + (char *) &pSMBr->hdr.Protocol);
3078 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3079 *pMask = le64_to_cpu(pfinfo->mask);
3083 cifs_buf_release(pSMB);
3085 goto GetExtAttrRetry;
3089 #endif /* CONFIG_POSIX */
3091 #ifdef CONFIG_CIFS_EXPERIMENTAL
3092 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3094 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3095 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3099 QUERY_SEC_DESC_REQ *pSMB;
3102 cFYI(1, ("GetCifsACL"));
3107 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3108 8 /* parm len */, tcon, (void **) &pSMB);
3112 pSMB->MaxParameterCount = cpu_to_le32(4);
3113 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3114 pSMB->MaxSetupCount = 0;
3115 pSMB->Fid = fid; /* file handle always le */
3116 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3118 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3119 pSMB->hdr.smb_buf_length += 11;
3120 iov[0].iov_base = (char *)pSMB;
3121 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3123 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3125 cifs_stats_inc(&tcon->num_acl_get);
3127 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3128 } else { /* decode response */
3132 struct smb_com_ntransact_rsp *pSMBr;
3135 /* validate_nttransact */
3136 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3137 &pdata, &parm_len, pbuflen);
3140 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3142 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3144 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3145 rc = -EIO; /* bad smb */
3150 /* BB check that data area is minimum length and as big as acl_len */
3152 acl_len = le32_to_cpu(*parm);
3153 if (acl_len != *pbuflen) {
3154 cERROR(1, ("acl length %d does not match %d",
3155 acl_len, *pbuflen));
3156 if (*pbuflen > acl_len)
3160 /* check if buffer is big enough for the acl
3161 header followed by the smallest SID */
3162 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3163 (*pbuflen >= 64 * 1024)) {
3164 cERROR(1, ("bad acl length %d", *pbuflen));
3168 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3169 if (*acl_inf == NULL) {
3173 memcpy(*acl_inf, pdata, *pbuflen);
3177 if (buf_type == CIFS_SMALL_BUFFER)
3178 cifs_small_buf_release(iov[0].iov_base);
3179 else if (buf_type == CIFS_LARGE_BUFFER)
3180 cifs_buf_release(iov[0].iov_base);
3181 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3186 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3187 struct cifs_ntsd *pntsd, __u32 acllen)
3189 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3191 int bytes_returned = 0;
3192 SET_SEC_DESC_REQ *pSMB = NULL;
3193 NTRANSACT_RSP *pSMBr = NULL;
3196 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3201 pSMB->MaxSetupCount = 0;
3205 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3206 data_count = acllen;
3207 data_offset = param_offset + param_count;
3208 byte_count = 3 /* pad */ + param_count;
3210 pSMB->DataCount = cpu_to_le32(data_count);
3211 pSMB->TotalDataCount = pSMB->DataCount;
3212 pSMB->MaxParameterCount = cpu_to_le32(4);
3213 pSMB->MaxDataCount = cpu_to_le32(16384);
3214 pSMB->ParameterCount = cpu_to_le32(param_count);
3215 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3216 pSMB->TotalParameterCount = pSMB->ParameterCount;
3217 pSMB->DataOffset = cpu_to_le32(data_offset);
3218 pSMB->SetupCount = 0;
3219 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3220 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3222 pSMB->Fid = fid; /* file handle always le */
3223 pSMB->Reserved2 = 0;
3224 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3226 if (pntsd && acllen) {
3227 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3230 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3233 pSMB->hdr.smb_buf_length += byte_count;
3235 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3236 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3238 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3240 cFYI(1, ("Set CIFS ACL returned %d", rc));
3241 cifs_buf_release(pSMB);
3244 goto setCifsAclRetry;
3249 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3251 /* Legacy Query Path Information call for lookup to old servers such
3253 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3254 const unsigned char *searchName,
3255 FILE_ALL_INFO *pFinfo,
3256 const struct nls_table *nls_codepage, int remap)
3258 QUERY_INFORMATION_REQ *pSMB;
3259 QUERY_INFORMATION_RSP *pSMBr;
3264 cFYI(1, ("In SMBQPath path %s", searchName));
3266 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3271 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3273 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3274 PATH_MAX, nls_codepage, remap);
3275 name_len++; /* trailing null */
3278 name_len = strnlen(searchName, PATH_MAX);
3279 name_len++; /* trailing null */
3280 strncpy(pSMB->FileName, searchName, name_len);
3282 pSMB->BufferFormat = 0x04;
3283 name_len++; /* account for buffer type byte */
3284 pSMB->hdr.smb_buf_length += (__u16) name_len;
3285 pSMB->ByteCount = cpu_to_le16(name_len);
3287 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3288 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3290 cFYI(1, ("Send error in QueryInfo = %d", rc));
3291 } else if (pFinfo) {
3293 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3295 /* decode response */
3296 /* BB FIXME - add time zone adjustment BB */
3297 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3300 /* decode time fields */
3301 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3302 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3303 pFinfo->LastAccessTime = 0;
3304 pFinfo->AllocationSize =
3305 cpu_to_le64(le32_to_cpu(pSMBr->size));
3306 pFinfo->EndOfFile = pFinfo->AllocationSize;
3307 pFinfo->Attributes =
3308 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3310 rc = -EIO; /* bad buffer passed in */
3312 cifs_buf_release(pSMB);
3324 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3325 const unsigned char *searchName,
3326 FILE_ALL_INFO *pFindData,
3327 int legacy /* old style infolevel */,
3328 const struct nls_table *nls_codepage, int remap)
3330 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3331 TRANSACTION2_QPI_REQ *pSMB = NULL;
3332 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3336 __u16 params, byte_count;
3338 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3340 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3345 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3347 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3348 PATH_MAX, nls_codepage, remap);
3349 name_len++; /* trailing null */
3351 } else { /* BB improve the check for buffer overruns BB */
3352 name_len = strnlen(searchName, PATH_MAX);
3353 name_len++; /* trailing null */
3354 strncpy(pSMB->FileName, searchName, name_len);
3357 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3358 pSMB->TotalDataCount = 0;
3359 pSMB->MaxParameterCount = cpu_to_le16(2);
3360 /* BB find exact max SMB PDU from sess structure BB */
3361 pSMB->MaxDataCount = cpu_to_le16(4000);
3362 pSMB->MaxSetupCount = 0;
3366 pSMB->Reserved2 = 0;
3367 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3368 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3369 pSMB->DataCount = 0;
3370 pSMB->DataOffset = 0;
3371 pSMB->SetupCount = 1;
3372 pSMB->Reserved3 = 0;
3373 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3374 byte_count = params + 1 /* pad */ ;
3375 pSMB->TotalParameterCount = cpu_to_le16(params);
3376 pSMB->ParameterCount = pSMB->TotalParameterCount;
3378 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3380 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3381 pSMB->Reserved4 = 0;
3382 pSMB->hdr.smb_buf_length += byte_count;
3383 pSMB->ByteCount = cpu_to_le16(byte_count);
3385 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3386 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3388 cFYI(1, ("Send error in QPathInfo = %d", rc));
3389 } else { /* decode response */
3390 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3392 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3394 else if (!legacy && (pSMBr->ByteCount < 40))
3395 rc = -EIO; /* bad smb */
3396 else if (legacy && (pSMBr->ByteCount < 24))
3397 rc = -EIO; /* 24 or 26 expected but we do not read
3399 else if (pFindData) {
3401 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3403 /* On legacy responses we do not read the last field,
3404 EAsize, fortunately since it varies by subdialect and
3405 also note it differs on Set vs. Get, ie two bytes or 4
3406 bytes depending but we don't care here */
3408 size = sizeof(FILE_INFO_STANDARD);
3410 size = sizeof(FILE_ALL_INFO);
3411 memcpy((char *) pFindData,
3412 (char *) &pSMBr->hdr.Protocol +
3417 cifs_buf_release(pSMB);
3419 goto QPathInfoRetry;
3425 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3426 const unsigned char *searchName,
3427 FILE_UNIX_BASIC_INFO *pFindData,
3428 const struct nls_table *nls_codepage, int remap)
3430 /* SMB_QUERY_FILE_UNIX_BASIC */
3431 TRANSACTION2_QPI_REQ *pSMB = NULL;
3432 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3434 int bytes_returned = 0;
3436 __u16 params, byte_count;
3438 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3440 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3445 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3447 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3448 PATH_MAX, nls_codepage, remap);
3449 name_len++; /* trailing null */
3451 } else { /* BB improve the check for buffer overruns BB */
3452 name_len = strnlen(searchName, PATH_MAX);
3453 name_len++; /* trailing null */
3454 strncpy(pSMB->FileName, searchName, name_len);
3457 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3458 pSMB->TotalDataCount = 0;
3459 pSMB->MaxParameterCount = cpu_to_le16(2);
3460 /* BB find exact max SMB PDU from sess structure BB */
3461 pSMB->MaxDataCount = cpu_to_le16(4000);
3462 pSMB->MaxSetupCount = 0;
3466 pSMB->Reserved2 = 0;
3467 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3468 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3469 pSMB->DataCount = 0;
3470 pSMB->DataOffset = 0;
3471 pSMB->SetupCount = 1;
3472 pSMB->Reserved3 = 0;
3473 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3474 byte_count = params + 1 /* pad */ ;
3475 pSMB->TotalParameterCount = cpu_to_le16(params);
3476 pSMB->ParameterCount = pSMB->TotalParameterCount;
3477 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3478 pSMB->Reserved4 = 0;
3479 pSMB->hdr.smb_buf_length += byte_count;
3480 pSMB->ByteCount = cpu_to_le16(byte_count);
3482 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3483 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3485 cFYI(1, ("Send error in QPathInfo = %d", rc));
3486 } else { /* decode response */
3487 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3489 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3490 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3491 "Unix Extensions can be disabled on mount "
3492 "by specifying the nosfu mount option."));
3493 rc = -EIO; /* bad smb */
3495 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3496 memcpy((char *) pFindData,
3497 (char *) &pSMBr->hdr.Protocol +
3499 sizeof(FILE_UNIX_BASIC_INFO));
3502 cifs_buf_release(pSMB);
3504 goto UnixQPathInfoRetry;
3509 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3511 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3512 const char *searchName,
3513 const struct nls_table *nls_codepage,
3515 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3517 /* level 257 SMB_ */
3518 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3519 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3520 T2_FFIRST_RSP_PARMS *parms;
3522 int bytes_returned = 0;
3524 __u16 params, byte_count;
3526 cFYI(1, ("In FindFirst for %s", searchName));
3529 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3534 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3536 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3537 PATH_MAX, nls_codepage, remap);
3538 /* We can not add the asterik earlier in case
3539 it got remapped to 0xF03A as if it were part of the
3540 directory name instead of a wildcard */
3542 pSMB->FileName[name_len] = dirsep;
3543 pSMB->FileName[name_len+1] = 0;
3544 pSMB->FileName[name_len+2] = '*';
3545 pSMB->FileName[name_len+3] = 0;
3546 name_len += 4; /* now the trailing null */
3547 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3548 pSMB->FileName[name_len+1] = 0;
3550 } else { /* BB add check for overrun of SMB buf BB */
3551 name_len = strnlen(searchName, PATH_MAX);
3552 /* BB fix here and in unicode clause above ie
3553 if (name_len > buffersize-header)
3554 free buffer exit; BB */
3555 strncpy(pSMB->FileName, searchName, name_len);
3556 pSMB->FileName[name_len] = dirsep;
3557 pSMB->FileName[name_len+1] = '*';
3558 pSMB->FileName[name_len+2] = 0;
3562 params = 12 + name_len /* includes null */ ;
3563 pSMB->TotalDataCount = 0; /* no EAs */
3564 pSMB->MaxParameterCount = cpu_to_le16(10);
3565 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3566 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3567 pSMB->MaxSetupCount = 0;
3571 pSMB->Reserved2 = 0;
3572 byte_count = params + 1 /* pad */ ;
3573 pSMB->TotalParameterCount = cpu_to_le16(params);
3574 pSMB->ParameterCount = pSMB->TotalParameterCount;
3575 pSMB->ParameterOffset = cpu_to_le16(
3576 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3578 pSMB->DataCount = 0;
3579 pSMB->DataOffset = 0;
3580 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3581 pSMB->Reserved3 = 0;
3582 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3583 pSMB->SearchAttributes =
3584 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3586 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3587 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3588 CIFS_SEARCH_RETURN_RESUME);
3589 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3591 /* BB what should we set StorageType to? Does it matter? BB */
3592 pSMB->SearchStorageType = 0;
3593 pSMB->hdr.smb_buf_length += byte_count;
3594 pSMB->ByteCount = cpu_to_le16(byte_count);
3596 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3597 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3598 cifs_stats_inc(&tcon->num_ffirst);
3600 if (rc) {/* BB add logic to retry regular search if Unix search
3601 rejected unexpectedly by server */
3602 /* BB Add code to handle unsupported level rc */
3603 cFYI(1, ("Error in FindFirst = %d", rc));
3605 cifs_buf_release(pSMB);
3607 /* BB eventually could optimize out free and realloc of buf */
3610 goto findFirstRetry;
3611 } else { /* decode response */
3612 /* BB remember to free buffer if error BB */
3613 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3617 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3618 psrch_inf->unicode = true;
3620 psrch_inf->unicode = false;
3622 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3623 psrch_inf->smallBuf = 0;
3624 psrch_inf->srch_entries_start =
3625 (char *) &pSMBr->hdr.Protocol +
3626 le16_to_cpu(pSMBr->t2.DataOffset);
3627 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3628 le16_to_cpu(pSMBr->t2.ParameterOffset));
3630 if (parms->EndofSearch)
3631 psrch_inf->endOfSearch = true;
3633 psrch_inf->endOfSearch = false;
3635 psrch_inf->entries_in_buffer =
3636 le16_to_cpu(parms->SearchCount);
3637 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3638 psrch_inf->entries_in_buffer;
3639 lnoff = le16_to_cpu(parms->LastNameOffset);
3640 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3642 cERROR(1, ("ignoring corrupt resume name"));
3643 psrch_inf->last_entry = NULL;
3647 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3650 *pnetfid = parms->SearchHandle;
3652 cifs_buf_release(pSMB);
3659 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3660 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3662 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3663 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3664 T2_FNEXT_RSP_PARMS *parms;
3665 char *response_data;
3667 int bytes_returned, name_len;
3668 __u16 params, byte_count;
3670 cFYI(1, ("In FindNext"));
3672 if (psrch_inf->endOfSearch)
3675 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3680 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3682 pSMB->TotalDataCount = 0; /* no EAs */
3683 pSMB->MaxParameterCount = cpu_to_le16(8);
3684 pSMB->MaxDataCount =
3685 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3687 pSMB->MaxSetupCount = 0;
3691 pSMB->Reserved2 = 0;
3692 pSMB->ParameterOffset = cpu_to_le16(
3693 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3694 pSMB->DataCount = 0;
3695 pSMB->DataOffset = 0;
3696 pSMB->SetupCount = 1;
3697 pSMB->Reserved3 = 0;
3698 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3699 pSMB->SearchHandle = searchHandle; /* always kept as le */
3701 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3702 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3703 pSMB->ResumeKey = psrch_inf->resume_key;
3705 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3707 name_len = psrch_inf->resume_name_len;
3709 if (name_len < PATH_MAX) {
3710 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3711 byte_count += name_len;
3712 /* 14 byte parm len above enough for 2 byte null terminator */
3713 pSMB->ResumeFileName[name_len] = 0;
3714 pSMB->ResumeFileName[name_len+1] = 0;
3717 goto FNext2_err_exit;
3719 byte_count = params + 1 /* pad */ ;
3720 pSMB->TotalParameterCount = cpu_to_le16(params);
3721 pSMB->ParameterCount = pSMB->TotalParameterCount;
3722 pSMB->hdr.smb_buf_length += byte_count;
3723 pSMB->ByteCount = cpu_to_le16(byte_count);
3725 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3726 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3727 cifs_stats_inc(&tcon->num_fnext);
3730 psrch_inf->endOfSearch = true;
3731 cifs_buf_release(pSMB);
3732 rc = 0; /* search probably was closed at end of search*/
3734 cFYI(1, ("FindNext returned = %d", rc));
3735 } else { /* decode response */
3736 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3741 /* BB fixme add lock for file (srch_info) struct here */
3742 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3743 psrch_inf->unicode = true;
3745 psrch_inf->unicode = false;
3746 response_data = (char *) &pSMBr->hdr.Protocol +
3747 le16_to_cpu(pSMBr->t2.ParameterOffset);
3748 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3749 response_data = (char *)&pSMBr->hdr.Protocol +
3750 le16_to_cpu(pSMBr->t2.DataOffset);
3751 if (psrch_inf->smallBuf)
3752 cifs_small_buf_release(
3753 psrch_inf->ntwrk_buf_start);
3755 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3756 psrch_inf->srch_entries_start = response_data;
3757 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3758 psrch_inf->smallBuf = 0;
3759 if (parms->EndofSearch)
3760 psrch_inf->endOfSearch = true;
3762 psrch_inf->endOfSearch = false;
3763 psrch_inf->entries_in_buffer =
3764 le16_to_cpu(parms->SearchCount);
3765 psrch_inf->index_of_last_entry +=
3766 psrch_inf->entries_in_buffer;
3767 lnoff = le16_to_cpu(parms->LastNameOffset);
3768 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3770 cERROR(1, ("ignoring corrupt resume name"));
3771 psrch_inf->last_entry = NULL;
3774 psrch_inf->last_entry =
3775 psrch_inf->srch_entries_start + lnoff;
3777 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3778 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3780 /* BB fixme add unlock here */
3785 /* BB On error, should we leave previous search buf (and count and
3786 last entry fields) intact or free the previous one? */
3788 /* Note: On -EAGAIN error only caller can retry on handle based calls
3789 since file handle passed in no longer valid */
3792 cifs_buf_release(pSMB);
3797 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3798 const __u16 searchHandle)
3801 FINDCLOSE_REQ *pSMB = NULL;
3803 cFYI(1, ("In CIFSSMBFindClose"));
3804 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3806 /* no sense returning error if session restarted
3807 as file handle has been closed */
3813 pSMB->FileID = searchHandle;
3814 pSMB->ByteCount = 0;
3815 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3817 cERROR(1, ("Send error in FindClose = %d", rc));
3819 cifs_stats_inc(&tcon->num_fclose);
3821 /* Since session is dead, search handle closed on server already */
3829 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3830 const unsigned char *searchName,
3831 __u64 *inode_number,
3832 const struct nls_table *nls_codepage, int remap)
3835 TRANSACTION2_QPI_REQ *pSMB = NULL;
3836 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3837 int name_len, bytes_returned;
3838 __u16 params, byte_count;
3840 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3844 GetInodeNumberRetry:
3845 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3850 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3852 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3853 PATH_MAX, nls_codepage, remap);
3854 name_len++; /* trailing null */
3856 } else { /* BB improve the check for buffer overruns BB */
3857 name_len = strnlen(searchName, PATH_MAX);
3858 name_len++; /* trailing null */
3859 strncpy(pSMB->FileName, searchName, name_len);
3862 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3863 pSMB->TotalDataCount = 0;
3864 pSMB->MaxParameterCount = cpu_to_le16(2);
3865 /* BB find exact max data count below from sess structure BB */
3866 pSMB->MaxDataCount = cpu_to_le16(4000);
3867 pSMB->MaxSetupCount = 0;
3871 pSMB->Reserved2 = 0;
3872 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3873 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3874 pSMB->DataCount = 0;
3875 pSMB->DataOffset = 0;
3876 pSMB->SetupCount = 1;
3877 pSMB->Reserved3 = 0;
3878 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3879 byte_count = params + 1 /* pad */ ;
3880 pSMB->TotalParameterCount = cpu_to_le16(params);
3881 pSMB->ParameterCount = pSMB->TotalParameterCount;
3882 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3883 pSMB->Reserved4 = 0;
3884 pSMB->hdr.smb_buf_length += byte_count;
3885 pSMB->ByteCount = cpu_to_le16(byte_count);
3887 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3888 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3890 cFYI(1, ("error %d in QueryInternalInfo", rc));
3892 /* decode response */
3893 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3894 if (rc || (pSMBr->ByteCount < 2))
3895 /* BB also check enough total bytes returned */
3896 /* If rc should we check for EOPNOSUPP and
3897 disable the srvino flag? or in caller? */
3898 rc = -EIO; /* bad smb */
3900 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3901 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3902 struct file_internal_info *pfinfo;
3903 /* BB Do we need a cast or hash here ? */
3905 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3907 goto GetInodeNumOut;
3909 pfinfo = (struct file_internal_info *)
3910 (data_offset + (char *) &pSMBr->hdr.Protocol);
3911 *inode_number = pfinfo->UniqueId;
3915 cifs_buf_release(pSMB);
3917 goto GetInodeNumberRetry;
3921 /* parses DFS refferal V3 structure
3922 * caller is responsible for freeing target_nodes
3925 * on failure - errno
3928 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3929 unsigned int *num_of_nodes,
3930 struct dfs_info3_param **target_nodes,
3931 const struct nls_table *nls_codepage)
3936 struct dfs_referral_level_3 *ref;
3938 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3942 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3944 if (*num_of_nodes < 1) {
3945 cERROR(1, ("num_referrals: must be at least > 0,"
3946 "but we get num_referrals = %d\n", *num_of_nodes));
3948 goto parse_DFS_referrals_exit;
3951 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3952 if (ref->VersionNumber != cpu_to_le16(3)) {
3953 cERROR(1, ("Referrals of V%d version are not supported,"
3954 "should be V3", le16_to_cpu(ref->VersionNumber)));
3956 goto parse_DFS_referrals_exit;
3959 /* get the upper boundary of the resp buffer */
3960 data_end = (char *)(&(pSMBr->PathConsumed)) +
3961 le16_to_cpu(pSMBr->t2.DataCount);
3963 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3965 le16_to_cpu(pSMBr->DFSFlags)));
3967 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3968 *num_of_nodes, GFP_KERNEL);
3969 if (*target_nodes == NULL) {
3970 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3972 goto parse_DFS_referrals_exit;
3975 /* collect neccessary data from referrals */
3976 for (i = 0; i < *num_of_nodes; i++) {
3979 struct dfs_info3_param *node = (*target_nodes)+i;
3981 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3982 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3983 node->server_type = le16_to_cpu(ref->ServerType);
3984 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3987 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3988 max_len = data_end - temp;
3989 rc = cifs_strncpy_to_host(&(node->path_name), temp,
3990 max_len, is_unicode, nls_codepage);
3992 goto parse_DFS_referrals_exit;
3994 /* copy link target UNC */
3995 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3996 max_len = data_end - temp;
3997 rc = cifs_strncpy_to_host(&(node->node_name), temp,
3998 max_len, is_unicode, nls_codepage);
4000 goto parse_DFS_referrals_exit;
4002 ref += le16_to_cpu(ref->Size);
4005 parse_DFS_referrals_exit:
4007 free_dfs_info_array(*target_nodes, *num_of_nodes);
4008 *target_nodes = NULL;
4015 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4016 const unsigned char *searchName,
4017 struct dfs_info3_param **target_nodes,
4018 unsigned int *num_of_nodes,
4019 const struct nls_table *nls_codepage, int remap)
4021 /* TRANS2_GET_DFS_REFERRAL */
4022 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4023 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4027 __u16 params, byte_count;
4029 *target_nodes = NULL;
4031 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4035 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4040 /* server pointer checked in called function,
4041 but should never be null here anyway */
4042 pSMB->hdr.Mid = GetNextMid(ses->server);
4043 pSMB->hdr.Tid = ses->ipc_tid;
4044 pSMB->hdr.Uid = ses->Suid;
4045 if (ses->capabilities & CAP_STATUS32)
4046 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4047 if (ses->capabilities & CAP_DFS)
4048 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4050 if (ses->capabilities & CAP_UNICODE) {
4051 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4053 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4054 searchName, PATH_MAX, nls_codepage, remap);
4055 name_len++; /* trailing null */
4057 } else { /* BB improve the check for buffer overruns BB */
4058 name_len = strnlen(searchName, PATH_MAX);
4059 name_len++; /* trailing null */
4060 strncpy(pSMB->RequestFileName, searchName, name_len);
4064 if (ses->server->secMode &
4065 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4066 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4069 pSMB->hdr.Uid = ses->Suid;
4071 params = 2 /* level */ + name_len /*includes null */ ;
4072 pSMB->TotalDataCount = 0;
4073 pSMB->DataCount = 0;
4074 pSMB->DataOffset = 0;
4075 pSMB->MaxParameterCount = 0;
4076 /* BB find exact max SMB PDU from sess structure BB */
4077 pSMB->MaxDataCount = cpu_to_le16(4000);
4078 pSMB->MaxSetupCount = 0;
4082 pSMB->Reserved2 = 0;
4083 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4084 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4085 pSMB->SetupCount = 1;
4086 pSMB->Reserved3 = 0;
4087 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4088 byte_count = params + 3 /* pad */ ;
4089 pSMB->ParameterCount = cpu_to_le16(params);
4090 pSMB->TotalParameterCount = pSMB->ParameterCount;
4091 pSMB->MaxReferralLevel = cpu_to_le16(3);
4092 pSMB->hdr.smb_buf_length += byte_count;
4093 pSMB->ByteCount = cpu_to_le16(byte_count);
4095 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4098 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4101 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4103 /* BB Also check if enough total bytes returned? */
4104 if (rc || (pSMBr->ByteCount < 17)) {
4105 rc = -EIO; /* bad smb */
4109 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4111 le16_to_cpu(pSMBr->t2.DataOffset)));
4113 /* parse returned result into more usable form */
4114 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4115 target_nodes, nls_codepage);
4118 cifs_buf_release(pSMB);
4126 /* Query File System Info such as free space to old servers such as Win 9x */
4128 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4130 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4131 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4132 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4133 FILE_SYSTEM_ALLOC_INFO *response_data;
4135 int bytes_returned = 0;
4136 __u16 params, byte_count;
4138 cFYI(1, ("OldQFSInfo"));
4140 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4145 params = 2; /* level */
4146 pSMB->TotalDataCount = 0;
4147 pSMB->MaxParameterCount = cpu_to_le16(2);
4148 pSMB->MaxDataCount = cpu_to_le16(1000);
4149 pSMB->MaxSetupCount = 0;
4153 pSMB->Reserved2 = 0;
4154 byte_count = params + 1 /* pad */ ;
4155 pSMB->TotalParameterCount = cpu_to_le16(params);
4156 pSMB->ParameterCount = pSMB->TotalParameterCount;
4157 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4158 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4159 pSMB->DataCount = 0;
4160 pSMB->DataOffset = 0;
4161 pSMB->SetupCount = 1;
4162 pSMB->Reserved3 = 0;
4163 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4164 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4165 pSMB->hdr.smb_buf_length += byte_count;
4166 pSMB->ByteCount = cpu_to_le16(byte_count);
4168 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4169 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4171 cFYI(1, ("Send error in QFSInfo = %d", rc));
4172 } else { /* decode response */
4173 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4175 if (rc || (pSMBr->ByteCount < 18))
4176 rc = -EIO; /* bad smb */
4178 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4179 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4180 pSMBr->ByteCount, data_offset));
4182 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4183 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4185 le16_to_cpu(response_data->BytesPerSector) *
4186 le32_to_cpu(response_data->
4187 SectorsPerAllocationUnit);
4189 le32_to_cpu(response_data->TotalAllocationUnits);
4190 FSData->f_bfree = FSData->f_bavail =
4191 le32_to_cpu(response_data->FreeAllocationUnits);
4193 ("Blocks: %lld Free: %lld Block size %ld",
4194 (unsigned long long)FSData->f_blocks,
4195 (unsigned long long)FSData->f_bfree,
4199 cifs_buf_release(pSMB);
4202 goto oldQFSInfoRetry;
4208 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4210 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4211 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4212 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4213 FILE_SYSTEM_INFO *response_data;
4215 int bytes_returned = 0;
4216 __u16 params, byte_count;
4218 cFYI(1, ("In QFSInfo"));
4220 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4225 params = 2; /* level */
4226 pSMB->TotalDataCount = 0;
4227 pSMB->MaxParameterCount = cpu_to_le16(2);
4228 pSMB->MaxDataCount = cpu_to_le16(1000);
4229 pSMB->MaxSetupCount = 0;
4233 pSMB->Reserved2 = 0;
4234 byte_count = params + 1 /* pad */ ;
4235 pSMB->TotalParameterCount = cpu_to_le16(params);
4236 pSMB->ParameterCount = pSMB->TotalParameterCount;
4237 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4238 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4239 pSMB->DataCount = 0;
4240 pSMB->DataOffset = 0;
4241 pSMB->SetupCount = 1;
4242 pSMB->Reserved3 = 0;
4243 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4244 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4245 pSMB->hdr.smb_buf_length += byte_count;
4246 pSMB->ByteCount = cpu_to_le16(byte_count);
4248 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4249 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4251 cFYI(1, ("Send error in QFSInfo = %d", rc));
4252 } else { /* decode response */
4253 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4255 if (rc || (pSMBr->ByteCount < 24))
4256 rc = -EIO; /* bad smb */
4258 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4262 *) (((char *) &pSMBr->hdr.Protocol) +
4265 le32_to_cpu(response_data->BytesPerSector) *
4266 le32_to_cpu(response_data->
4267 SectorsPerAllocationUnit);
4269 le64_to_cpu(response_data->TotalAllocationUnits);
4270 FSData->f_bfree = FSData->f_bavail =
4271 le64_to_cpu(response_data->FreeAllocationUnits);
4273 ("Blocks: %lld Free: %lld Block size %ld",
4274 (unsigned long long)FSData->f_blocks,
4275 (unsigned long long)FSData->f_bfree,
4279 cifs_buf_release(pSMB);
4288 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4290 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4291 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4292 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4293 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4295 int bytes_returned = 0;
4296 __u16 params, byte_count;
4298 cFYI(1, ("In QFSAttributeInfo"));
4300 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4305 params = 2; /* level */
4306 pSMB->TotalDataCount = 0;
4307 pSMB->MaxParameterCount = cpu_to_le16(2);
4308 /* BB find exact max SMB PDU from sess structure BB */
4309 pSMB->MaxDataCount = cpu_to_le16(1000);
4310 pSMB->MaxSetupCount = 0;
4314 pSMB->Reserved2 = 0;
4315 byte_count = params + 1 /* pad */ ;
4316 pSMB->TotalParameterCount = cpu_to_le16(params);
4317 pSMB->ParameterCount = pSMB->TotalParameterCount;
4318 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4319 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4320 pSMB->DataCount = 0;
4321 pSMB->DataOffset = 0;
4322 pSMB->SetupCount = 1;
4323 pSMB->Reserved3 = 0;
4324 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4325 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4326 pSMB->hdr.smb_buf_length += byte_count;
4327 pSMB->ByteCount = cpu_to_le16(byte_count);
4329 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4330 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4332 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4333 } else { /* decode response */
4334 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4336 if (rc || (pSMBr->ByteCount < 13)) {
4337 /* BB also check if enough bytes returned */
4338 rc = -EIO; /* bad smb */
4340 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4342 (FILE_SYSTEM_ATTRIBUTE_INFO
4343 *) (((char *) &pSMBr->hdr.Protocol) +
4345 memcpy(&tcon->fsAttrInfo, response_data,
4346 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4349 cifs_buf_release(pSMB);
4352 goto QFSAttributeRetry;
4358 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4360 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4361 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4362 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4363 FILE_SYSTEM_DEVICE_INFO *response_data;
4365 int bytes_returned = 0;
4366 __u16 params, byte_count;
4368 cFYI(1, ("In QFSDeviceInfo"));
4370 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4375 params = 2; /* level */
4376 pSMB->TotalDataCount = 0;
4377 pSMB->MaxParameterCount = cpu_to_le16(2);
4378 /* BB find exact max SMB PDU from sess structure BB */
4379 pSMB->MaxDataCount = cpu_to_le16(1000);
4380 pSMB->MaxSetupCount = 0;
4384 pSMB->Reserved2 = 0;
4385 byte_count = params + 1 /* pad */ ;
4386 pSMB->TotalParameterCount = cpu_to_le16(params);
4387 pSMB->ParameterCount = pSMB->TotalParameterCount;
4388 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4389 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4391 pSMB->DataCount = 0;
4392 pSMB->DataOffset = 0;
4393 pSMB->SetupCount = 1;
4394 pSMB->Reserved3 = 0;
4395 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4396 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4397 pSMB->hdr.smb_buf_length += byte_count;
4398 pSMB->ByteCount = cpu_to_le16(byte_count);
4400 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4401 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4403 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4404 } else { /* decode response */
4405 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4407 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4408 rc = -EIO; /* bad smb */
4410 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4412 (FILE_SYSTEM_DEVICE_INFO *)
4413 (((char *) &pSMBr->hdr.Protocol) +
4415 memcpy(&tcon->fsDevInfo, response_data,
4416 sizeof(FILE_SYSTEM_DEVICE_INFO));
4419 cifs_buf_release(pSMB);
4422 goto QFSDeviceRetry;
4428 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4430 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4431 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4432 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4433 FILE_SYSTEM_UNIX_INFO *response_data;
4435 int bytes_returned = 0;
4436 __u16 params, byte_count;
4438 cFYI(1, ("In QFSUnixInfo"));
4440 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4445 params = 2; /* level */
4446 pSMB->TotalDataCount = 0;
4447 pSMB->DataCount = 0;
4448 pSMB->DataOffset = 0;
4449 pSMB->MaxParameterCount = cpu_to_le16(2);
4450 /* BB find exact max SMB PDU from sess structure BB */
4451 pSMB->MaxDataCount = cpu_to_le16(100);
4452 pSMB->MaxSetupCount = 0;
4456 pSMB->Reserved2 = 0;
4457 byte_count = params + 1 /* pad */ ;
4458 pSMB->ParameterCount = cpu_to_le16(params);
4459 pSMB->TotalParameterCount = pSMB->ParameterCount;
4460 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4461 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4462 pSMB->SetupCount = 1;
4463 pSMB->Reserved3 = 0;
4464 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4465 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4466 pSMB->hdr.smb_buf_length += byte_count;
4467 pSMB->ByteCount = cpu_to_le16(byte_count);
4469 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4470 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4472 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4473 } else { /* decode response */
4474 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4476 if (rc || (pSMBr->ByteCount < 13)) {
4477 rc = -EIO; /* bad smb */
4479 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4481 (FILE_SYSTEM_UNIX_INFO
4482 *) (((char *) &pSMBr->hdr.Protocol) +
4484 memcpy(&tcon->fsUnixInfo, response_data,
4485 sizeof(FILE_SYSTEM_UNIX_INFO));
4488 cifs_buf_release(pSMB);
4498 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4500 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4501 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4502 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4504 int bytes_returned = 0;
4505 __u16 params, param_offset, offset, byte_count;
4507 cFYI(1, ("In SETFSUnixInfo"));
4509 /* BB switch to small buf init to save memory */
4510 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4515 params = 4; /* 2 bytes zero followed by info level. */
4516 pSMB->MaxSetupCount = 0;
4520 pSMB->Reserved2 = 0;
4521 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4523 offset = param_offset + params;
4525 pSMB->MaxParameterCount = cpu_to_le16(4);
4526 /* BB find exact max SMB PDU from sess structure BB */
4527 pSMB->MaxDataCount = cpu_to_le16(100);
4528 pSMB->SetupCount = 1;
4529 pSMB->Reserved3 = 0;
4530 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4531 byte_count = 1 /* pad */ + params + 12;
4533 pSMB->DataCount = cpu_to_le16(12);
4534 pSMB->ParameterCount = cpu_to_le16(params);
4535 pSMB->TotalDataCount = pSMB->DataCount;
4536 pSMB->TotalParameterCount = pSMB->ParameterCount;
4537 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4538 pSMB->DataOffset = cpu_to_le16(offset);
4542 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4545 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4546 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4547 pSMB->ClientUnixCap = cpu_to_le64(cap);
4549 pSMB->hdr.smb_buf_length += byte_count;
4550 pSMB->ByteCount = cpu_to_le16(byte_count);
4552 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4553 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4555 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4556 } else { /* decode response */
4557 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4559 rc = -EIO; /* bad smb */
4561 cifs_buf_release(pSMB);
4564 goto SETFSUnixRetry;
4572 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4573 struct kstatfs *FSData)
4575 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4576 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4577 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4578 FILE_SYSTEM_POSIX_INFO *response_data;
4580 int bytes_returned = 0;
4581 __u16 params, byte_count;
4583 cFYI(1, ("In QFSPosixInfo"));
4585 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4590 params = 2; /* level */
4591 pSMB->TotalDataCount = 0;
4592 pSMB->DataCount = 0;
4593 pSMB->DataOffset = 0;
4594 pSMB->MaxParameterCount = cpu_to_le16(2);
4595 /* BB find exact max SMB PDU from sess structure BB */
4596 pSMB->MaxDataCount = cpu_to_le16(100);
4597 pSMB->MaxSetupCount = 0;
4601 pSMB->Reserved2 = 0;
4602 byte_count = params + 1 /* pad */ ;
4603 pSMB->ParameterCount = cpu_to_le16(params);
4604 pSMB->TotalParameterCount = pSMB->ParameterCount;
4605 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4606 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4607 pSMB->SetupCount = 1;
4608 pSMB->Reserved3 = 0;
4609 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4610 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4611 pSMB->hdr.smb_buf_length += byte_count;
4612 pSMB->ByteCount = cpu_to_le16(byte_count);
4614 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4615 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4617 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4618 } else { /* decode response */
4619 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4621 if (rc || (pSMBr->ByteCount < 13)) {
4622 rc = -EIO; /* bad smb */
4624 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4626 (FILE_SYSTEM_POSIX_INFO
4627 *) (((char *) &pSMBr->hdr.Protocol) +
4630 le32_to_cpu(response_data->BlockSize);
4632 le64_to_cpu(response_data->TotalBlocks);
4634 le64_to_cpu(response_data->BlocksAvail);
4635 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4636 FSData->f_bavail = FSData->f_bfree;
4639 le64_to_cpu(response_data->UserBlocksAvail);
4641 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4643 le64_to_cpu(response_data->TotalFileNodes);
4644 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4646 le64_to_cpu(response_data->FreeFileNodes);
4649 cifs_buf_release(pSMB);
4658 /* We can not use write of zero bytes trick to
4659 set file size due to need for large file support. Also note that
4660 this SetPathInfo is preferred to SetFileInfo based method in next
4661 routine which is only needed to work around a sharing violation bug
4662 in Samba which this routine can run into */
4665 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4666 __u64 size, bool SetAllocation,
4667 const struct nls_table *nls_codepage, int remap)
4669 struct smb_com_transaction2_spi_req *pSMB = NULL;
4670 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4671 struct file_end_of_file_info *parm_data;
4674 int bytes_returned = 0;
4675 __u16 params, byte_count, data_count, param_offset, offset;
4677 cFYI(1, ("In SetEOF"));
4679 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4684 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4686 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4687 PATH_MAX, nls_codepage, remap);
4688 name_len++; /* trailing null */
4690 } else { /* BB improve the check for buffer overruns BB */
4691 name_len = strnlen(fileName, PATH_MAX);
4692 name_len++; /* trailing null */
4693 strncpy(pSMB->FileName, fileName, name_len);
4695 params = 6 + name_len;
4696 data_count = sizeof(struct file_end_of_file_info);
4697 pSMB->MaxParameterCount = cpu_to_le16(2);
4698 pSMB->MaxDataCount = cpu_to_le16(4100);
4699 pSMB->MaxSetupCount = 0;
4703 pSMB->Reserved2 = 0;
4704 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4705 InformationLevel) - 4;
4706 offset = param_offset + params;
4707 if (SetAllocation) {
4708 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4709 pSMB->InformationLevel =
4710 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4712 pSMB->InformationLevel =
4713 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4714 } else /* Set File Size */ {
4715 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4716 pSMB->InformationLevel =
4717 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4719 pSMB->InformationLevel =
4720 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4724 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4726 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4727 pSMB->DataOffset = cpu_to_le16(offset);
4728 pSMB->SetupCount = 1;
4729 pSMB->Reserved3 = 0;
4730 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4731 byte_count = 3 /* pad */ + params + data_count;
4732 pSMB->DataCount = cpu_to_le16(data_count);
4733 pSMB->TotalDataCount = pSMB->DataCount;
4734 pSMB->ParameterCount = cpu_to_le16(params);
4735 pSMB->TotalParameterCount = pSMB->ParameterCount;
4736 pSMB->Reserved4 = 0;
4737 pSMB->hdr.smb_buf_length += byte_count;
4738 parm_data->FileSize = cpu_to_le64(size);
4739 pSMB->ByteCount = cpu_to_le16(byte_count);
4740 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4741 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4743 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4745 cifs_buf_release(pSMB);
4754 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4755 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4757 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4759 struct file_end_of_file_info *parm_data;
4761 __u16 params, param_offset, offset, byte_count, count;
4763 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4765 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4770 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4771 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4774 pSMB->MaxSetupCount = 0;
4778 pSMB->Reserved2 = 0;
4779 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4780 offset = param_offset + params;
4782 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4784 count = sizeof(struct file_end_of_file_info);
4785 pSMB->MaxParameterCount = cpu_to_le16(2);
4786 /* BB find exact max SMB PDU from sess structure BB */
4787 pSMB->MaxDataCount = cpu_to_le16(1000);
4788 pSMB->SetupCount = 1;
4789 pSMB->Reserved3 = 0;
4790 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4791 byte_count = 3 /* pad */ + params + count;
4792 pSMB->DataCount = cpu_to_le16(count);
4793 pSMB->ParameterCount = cpu_to_le16(params);
4794 pSMB->TotalDataCount = pSMB->DataCount;
4795 pSMB->TotalParameterCount = pSMB->ParameterCount;
4796 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4798 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4800 pSMB->DataOffset = cpu_to_le16(offset);
4801 parm_data->FileSize = cpu_to_le64(size);
4803 if (SetAllocation) {
4804 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4805 pSMB->InformationLevel =
4806 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4808 pSMB->InformationLevel =
4809 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4810 } else /* Set File Size */ {
4811 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4812 pSMB->InformationLevel =
4813 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4815 pSMB->InformationLevel =
4816 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4818 pSMB->Reserved4 = 0;
4819 pSMB->hdr.smb_buf_length += byte_count;
4820 pSMB->ByteCount = cpu_to_le16(byte_count);
4821 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4824 ("Send error in SetFileInfo (SetFileSize) = %d",
4828 /* Note: On -EAGAIN error only caller can retry on handle based calls
4829 since file handle passed in no longer valid */
4834 /* Some legacy servers such as NT4 require that the file times be set on
4835 an open handle, rather than by pathname - this is awkward due to
4836 potential access conflicts on the open, but it is unavoidable for these
4837 old servers since the only other choice is to go from 100 nanosecond DCE
4838 time and resort to the original setpathinfo level which takes the ancient
4839 DOS time format with 2 second granularity */
4841 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4842 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4844 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4847 __u16 params, param_offset, offset, byte_count, count;
4849 cFYI(1, ("Set Times (via SetFileInfo)"));
4850 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4855 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4856 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4859 pSMB->MaxSetupCount = 0;
4863 pSMB->Reserved2 = 0;
4864 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4865 offset = param_offset + params;
4867 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4869 count = sizeof(FILE_BASIC_INFO);
4870 pSMB->MaxParameterCount = cpu_to_le16(2);
4871 /* BB find max SMB PDU from sess */
4872 pSMB->MaxDataCount = cpu_to_le16(1000);
4873 pSMB->SetupCount = 1;
4874 pSMB->Reserved3 = 0;
4875 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4876 byte_count = 3 /* pad */ + params + count;
4877 pSMB->DataCount = cpu_to_le16(count);
4878 pSMB->ParameterCount = cpu_to_le16(params);
4879 pSMB->TotalDataCount = pSMB->DataCount;
4880 pSMB->TotalParameterCount = pSMB->ParameterCount;
4881 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4882 pSMB->DataOffset = cpu_to_le16(offset);
4884 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4885 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4887 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4888 pSMB->Reserved4 = 0;
4889 pSMB->hdr.smb_buf_length += byte_count;
4890 pSMB->ByteCount = cpu_to_le16(byte_count);
4891 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4892 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4894 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4896 /* Note: On -EAGAIN error only caller can retry on handle based calls
4897 since file handle passed in no longer valid */
4903 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4904 bool delete_file, __u16 fid, __u32 pid_of_opener)
4906 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4909 __u16 params, param_offset, offset, byte_count, count;
4911 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4912 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4917 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4918 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4921 pSMB->MaxSetupCount = 0;
4925 pSMB->Reserved2 = 0;
4926 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4927 offset = param_offset + params;
4929 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4932 pSMB->MaxParameterCount = cpu_to_le16(2);
4933 /* BB find max SMB PDU from sess */
4934 pSMB->MaxDataCount = cpu_to_le16(1000);
4935 pSMB->SetupCount = 1;
4936 pSMB->Reserved3 = 0;
4937 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4938 byte_count = 3 /* pad */ + params + count;
4939 pSMB->DataCount = cpu_to_le16(count);
4940 pSMB->ParameterCount = cpu_to_le16(params);
4941 pSMB->TotalDataCount = pSMB->DataCount;
4942 pSMB->TotalParameterCount = pSMB->ParameterCount;
4943 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4944 pSMB->DataOffset = cpu_to_le16(offset);
4946 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4947 pSMB->Reserved4 = 0;
4948 pSMB->hdr.smb_buf_length += byte_count;
4949 pSMB->ByteCount = cpu_to_le16(byte_count);
4950 *data_offset = delete_file ? 1 : 0;
4951 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4953 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4959 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4960 const char *fileName, const FILE_BASIC_INFO *data,
4961 const struct nls_table *nls_codepage, int remap)
4963 TRANSACTION2_SPI_REQ *pSMB = NULL;
4964 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4967 int bytes_returned = 0;
4969 __u16 params, param_offset, offset, byte_count, count;
4971 cFYI(1, ("In SetTimes"));
4974 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4979 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4981 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4982 PATH_MAX, nls_codepage, remap);
4983 name_len++; /* trailing null */
4985 } else { /* BB improve the check for buffer overruns BB */
4986 name_len = strnlen(fileName, PATH_MAX);
4987 name_len++; /* trailing null */
4988 strncpy(pSMB->FileName, fileName, name_len);
4991 params = 6 + name_len;
4992 count = sizeof(FILE_BASIC_INFO);
4993 pSMB->MaxParameterCount = cpu_to_le16(2);
4994 /* BB find max SMB PDU from sess structure BB */
4995 pSMB->MaxDataCount = cpu_to_le16(1000);
4996 pSMB->MaxSetupCount = 0;
5000 pSMB->Reserved2 = 0;
5001 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5002 InformationLevel) - 4;
5003 offset = param_offset + params;
5004 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5005 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5006 pSMB->DataOffset = cpu_to_le16(offset);
5007 pSMB->SetupCount = 1;
5008 pSMB->Reserved3 = 0;
5009 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5010 byte_count = 3 /* pad */ + params + count;
5012 pSMB->DataCount = cpu_to_le16(count);
5013 pSMB->ParameterCount = cpu_to_le16(params);
5014 pSMB->TotalDataCount = pSMB->DataCount;
5015 pSMB->TotalParameterCount = pSMB->ParameterCount;
5016 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5017 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5019 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5020 pSMB->Reserved4 = 0;
5021 pSMB->hdr.smb_buf_length += byte_count;
5022 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5023 pSMB->ByteCount = cpu_to_le16(byte_count);
5024 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5025 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5027 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5029 cifs_buf_release(pSMB);
5037 /* Can not be used to set time stamps yet (due to old DOS time format) */
5038 /* Can be used to set attributes */
5039 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5040 handling it anyway and NT4 was what we thought it would be needed for
5041 Do not delete it until we prove whether needed for Win9x though */
5043 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5044 __u16 dos_attrs, const struct nls_table *nls_codepage)
5046 SETATTR_REQ *pSMB = NULL;
5047 SETATTR_RSP *pSMBr = NULL;
5052 cFYI(1, ("In SetAttrLegacy"));
5055 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5060 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5062 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5063 PATH_MAX, nls_codepage);
5064 name_len++; /* trailing null */
5066 } else { /* BB improve the check for buffer overruns BB */
5067 name_len = strnlen(fileName, PATH_MAX);
5068 name_len++; /* trailing null */
5069 strncpy(pSMB->fileName, fileName, name_len);
5071 pSMB->attr = cpu_to_le16(dos_attrs);
5072 pSMB->BufferFormat = 0x04;
5073 pSMB->hdr.smb_buf_length += name_len + 1;
5074 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5075 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5076 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5078 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5080 cifs_buf_release(pSMB);
5083 goto SetAttrLgcyRetry;
5087 #endif /* temporarily unneeded SetAttr legacy function */
5090 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5091 const struct cifs_unix_set_info_args *args,
5092 const struct nls_table *nls_codepage, int remap)
5094 TRANSACTION2_SPI_REQ *pSMB = NULL;
5095 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5098 int bytes_returned = 0;
5099 FILE_UNIX_BASIC_INFO *data_offset;
5100 __u16 params, param_offset, offset, count, byte_count;
5101 __u64 mode = args->mode;
5103 cFYI(1, ("In SetUID/GID/Mode"));
5105 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5110 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5112 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5113 PATH_MAX, nls_codepage, remap);
5114 name_len++; /* trailing null */
5116 } else { /* BB improve the check for buffer overruns BB */
5117 name_len = strnlen(fileName, PATH_MAX);
5118 name_len++; /* trailing null */
5119 strncpy(pSMB->FileName, fileName, name_len);
5122 params = 6 + name_len;
5123 count = sizeof(FILE_UNIX_BASIC_INFO);
5124 pSMB->MaxParameterCount = cpu_to_le16(2);
5125 /* BB find max SMB PDU from sess structure BB */
5126 pSMB->MaxDataCount = cpu_to_le16(1000);
5127 pSMB->MaxSetupCount = 0;
5131 pSMB->Reserved2 = 0;
5132 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5133 InformationLevel) - 4;
5134 offset = param_offset + params;
5136 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5138 memset(data_offset, 0, count);
5139 pSMB->DataOffset = cpu_to_le16(offset);
5140 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5141 pSMB->SetupCount = 1;
5142 pSMB->Reserved3 = 0;
5143 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5144 byte_count = 3 /* pad */ + params + count;
5145 pSMB->ParameterCount = cpu_to_le16(params);
5146 pSMB->DataCount = cpu_to_le16(count);
5147 pSMB->TotalParameterCount = pSMB->ParameterCount;
5148 pSMB->TotalDataCount = pSMB->DataCount;
5149 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5150 pSMB->Reserved4 = 0;
5151 pSMB->hdr.smb_buf_length += byte_count;
5152 /* Samba server ignores set of file size to zero due to bugs in some
5153 older clients, but we should be precise - we use SetFileSize to
5154 set file size and do not want to truncate file size to zero
5155 accidently as happened on one Samba server beta by putting
5156 zero instead of -1 here */
5157 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5158 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5159 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5160 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5161 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5162 data_offset->Uid = cpu_to_le64(args->uid);
5163 data_offset->Gid = cpu_to_le64(args->gid);
5164 /* better to leave device as zero when it is */
5165 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5166 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5167 data_offset->Permissions = cpu_to_le64(mode);
5170 data_offset->Type = cpu_to_le32(UNIX_FILE);
5171 else if (S_ISDIR(mode))
5172 data_offset->Type = cpu_to_le32(UNIX_DIR);
5173 else if (S_ISLNK(mode))
5174 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5175 else if (S_ISCHR(mode))
5176 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5177 else if (S_ISBLK(mode))
5178 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5179 else if (S_ISFIFO(mode))
5180 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5181 else if (S_ISSOCK(mode))
5182 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5185 pSMB->ByteCount = cpu_to_le16(byte_count);
5186 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5187 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5189 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5191 cifs_buf_release(pSMB);
5197 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5198 const int notify_subdirs, const __u16 netfid,
5199 __u32 filter, struct file *pfile, int multishot,
5200 const struct nls_table *nls_codepage)
5203 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5204 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5205 struct dir_notify_req *dnotify_req;
5208 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5209 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5214 pSMB->TotalParameterCount = 0 ;
5215 pSMB->TotalDataCount = 0;
5216 pSMB->MaxParameterCount = cpu_to_le32(2);
5217 /* BB find exact data count max from sess structure BB */
5218 pSMB->MaxDataCount = 0; /* same in little endian or be */
5219 /* BB VERIFY verify which is correct for above BB */
5220 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5221 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5223 pSMB->MaxSetupCount = 4;
5225 pSMB->ParameterOffset = 0;
5226 pSMB->DataCount = 0;
5227 pSMB->DataOffset = 0;
5228 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5229 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5230 pSMB->ParameterCount = pSMB->TotalParameterCount;
5232 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5233 pSMB->Reserved2 = 0;
5234 pSMB->CompletionFilter = cpu_to_le32(filter);
5235 pSMB->Fid = netfid; /* file handle always le */
5236 pSMB->ByteCount = 0;
5238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5239 (struct smb_hdr *)pSMBr, &bytes_returned,
5242 cFYI(1, ("Error in Notify = %d", rc));
5244 /* Add file to outstanding requests */
5245 /* BB change to kmem cache alloc */
5246 dnotify_req = kmalloc(
5247 sizeof(struct dir_notify_req),
5250 dnotify_req->Pid = pSMB->hdr.Pid;
5251 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5252 dnotify_req->Mid = pSMB->hdr.Mid;
5253 dnotify_req->Tid = pSMB->hdr.Tid;
5254 dnotify_req->Uid = pSMB->hdr.Uid;
5255 dnotify_req->netfid = netfid;
5256 dnotify_req->pfile = pfile;
5257 dnotify_req->filter = filter;
5258 dnotify_req->multishot = multishot;
5259 spin_lock(&GlobalMid_Lock);
5260 list_add_tail(&dnotify_req->lhead,
5261 &GlobalDnotifyReqList);
5262 spin_unlock(&GlobalMid_Lock);
5266 cifs_buf_release(pSMB);
5269 #ifdef CONFIG_CIFS_XATTR
5271 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5272 const unsigned char *searchName,
5273 char *EAData, size_t buf_size,
5274 const struct nls_table *nls_codepage, int remap)
5276 /* BB assumes one setup word */
5277 TRANSACTION2_QPI_REQ *pSMB = NULL;
5278 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5282 struct fea *temp_fea;
5284 __u16 params, byte_count;
5286 cFYI(1, ("In Query All EAs path %s", searchName));
5288 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5293 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5295 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5296 PATH_MAX, nls_codepage, remap);
5297 name_len++; /* trailing null */
5299 } else { /* BB improve the check for buffer overruns BB */
5300 name_len = strnlen(searchName, PATH_MAX);
5301 name_len++; /* trailing null */
5302 strncpy(pSMB->FileName, searchName, name_len);
5305 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5306 pSMB->TotalDataCount = 0;
5307 pSMB->MaxParameterCount = cpu_to_le16(2);
5308 /* BB find exact max SMB PDU from sess structure BB */
5309 pSMB->MaxDataCount = cpu_to_le16(4000);
5310 pSMB->MaxSetupCount = 0;
5314 pSMB->Reserved2 = 0;
5315 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5316 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5317 pSMB->DataCount = 0;
5318 pSMB->DataOffset = 0;
5319 pSMB->SetupCount = 1;
5320 pSMB->Reserved3 = 0;
5321 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5322 byte_count = params + 1 /* pad */ ;
5323 pSMB->TotalParameterCount = cpu_to_le16(params);
5324 pSMB->ParameterCount = pSMB->TotalParameterCount;
5325 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5326 pSMB->Reserved4 = 0;
5327 pSMB->hdr.smb_buf_length += byte_count;
5328 pSMB->ByteCount = cpu_to_le16(byte_count);
5330 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5331 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5333 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5334 } else { /* decode response */
5335 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5337 /* BB also check enough total bytes returned */
5338 /* BB we need to improve the validity checking
5339 of these trans2 responses */
5340 if (rc || (pSMBr->ByteCount < 4))
5341 rc = -EIO; /* bad smb */
5342 /* else if (pFindData){
5343 memcpy((char *) pFindData,
5344 (char *) &pSMBr->hdr.Protocol +
5347 /* check that length of list is not more than bcc */
5348 /* check that each entry does not go beyond length
5350 /* check that each element of each entry does not
5351 go beyond end of list */
5352 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5353 struct fealist *ea_response_data;
5355 /* validate_trans2_offsets() */
5356 /* BB check if start of smb + data_offset > &bcc+ bcc */
5357 ea_response_data = (struct fealist *)
5358 (((char *) &pSMBr->hdr.Protocol) +
5360 name_len = le32_to_cpu(ea_response_data->list_len);
5361 cFYI(1, ("ea length %d", name_len));
5362 if (name_len <= 8) {
5363 /* returned EA size zeroed at top of function */
5364 cFYI(1, ("empty EA list returned from server"));
5366 /* account for ea list len */
5368 temp_fea = ea_response_data->list;
5369 temp_ptr = (char *)temp_fea;
5370 while (name_len > 0) {
5374 rc += temp_fea->name_len;
5375 /* account for prefix user. and trailing null */
5377 if (rc < (int)buf_size) {
5378 memcpy(EAData, "user.", 5);
5380 memcpy(EAData, temp_ptr,
5381 temp_fea->name_len);
5382 EAData += temp_fea->name_len;
5383 /* null terminate name */
5385 EAData = EAData + 1;
5386 } else if (buf_size == 0) {
5387 /* skip copy - calc size only */
5389 /* stop before overrun buffer */
5393 name_len -= temp_fea->name_len;
5394 temp_ptr += temp_fea->name_len;
5395 /* account for trailing null */
5399 le16_to_cpu(temp_fea->value_len);
5400 name_len -= value_len;
5401 temp_ptr += value_len;
5402 /* BB check that temp_ptr is still
5405 /* no trailing null to account for
5407 /* go on to next EA */
5408 temp_fea = (struct fea *)temp_ptr;
5413 cifs_buf_release(pSMB);
5420 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5421 const unsigned char *searchName, const unsigned char *ea_name,
5422 unsigned char *ea_value, size_t buf_size,
5423 const struct nls_table *nls_codepage, int remap)
5425 TRANSACTION2_QPI_REQ *pSMB = NULL;
5426 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5430 struct fea *temp_fea;
5432 __u16 params, byte_count;
5434 cFYI(1, ("In Query EA path %s", searchName));
5436 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5441 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5443 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5444 PATH_MAX, nls_codepage, remap);
5445 name_len++; /* trailing null */
5447 } else { /* BB improve the check for buffer overruns BB */
5448 name_len = strnlen(searchName, PATH_MAX);
5449 name_len++; /* trailing null */
5450 strncpy(pSMB->FileName, searchName, name_len);
5453 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5454 pSMB->TotalDataCount = 0;
5455 pSMB->MaxParameterCount = cpu_to_le16(2);
5456 /* BB find exact max SMB PDU from sess structure BB */
5457 pSMB->MaxDataCount = cpu_to_le16(4000);
5458 pSMB->MaxSetupCount = 0;
5462 pSMB->Reserved2 = 0;
5463 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5464 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5465 pSMB->DataCount = 0;
5466 pSMB->DataOffset = 0;
5467 pSMB->SetupCount = 1;
5468 pSMB->Reserved3 = 0;
5469 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5470 byte_count = params + 1 /* pad */ ;
5471 pSMB->TotalParameterCount = cpu_to_le16(params);
5472 pSMB->ParameterCount = pSMB->TotalParameterCount;
5473 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5474 pSMB->Reserved4 = 0;
5475 pSMB->hdr.smb_buf_length += byte_count;
5476 pSMB->ByteCount = cpu_to_le16(byte_count);
5478 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5479 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5481 cFYI(1, ("Send error in Query EA = %d", rc));
5482 } else { /* decode response */
5483 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5485 /* BB also check enough total bytes returned */
5486 /* BB we need to improve the validity checking
5487 of these trans2 responses */
5488 if (rc || (pSMBr->ByteCount < 4))
5489 rc = -EIO; /* bad smb */
5490 /* else if (pFindData){
5491 memcpy((char *) pFindData,
5492 (char *) &pSMBr->hdr.Protocol +
5495 /* check that length of list is not more than bcc */
5496 /* check that each entry does not go beyond length
5498 /* check that each element of each entry does not
5499 go beyond end of list */
5500 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5501 struct fealist *ea_response_data;
5503 /* validate_trans2_offsets() */
5504 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5505 ea_response_data = (struct fealist *)
5506 (((char *) &pSMBr->hdr.Protocol) +
5508 name_len = le32_to_cpu(ea_response_data->list_len);
5509 cFYI(1, ("ea length %d", name_len));
5510 if (name_len <= 8) {
5511 /* returned EA size zeroed at top of function */
5512 cFYI(1, ("empty EA list returned from server"));
5514 /* account for ea list len */
5516 temp_fea = ea_response_data->list;
5517 temp_ptr = (char *)temp_fea;
5518 /* loop through checking if we have a matching
5519 name and then return the associated value */
5520 while (name_len > 0) {
5525 le16_to_cpu(temp_fea->value_len);
5526 /* BB validate that value_len falls within SMB,
5527 even though maximum for name_len is 255 */
5528 if (memcmp(temp_fea->name, ea_name,
5529 temp_fea->name_len) == 0) {
5532 /* account for prefix user. and trailing null */
5533 if (rc <= (int)buf_size) {
5535 temp_fea->name+temp_fea->name_len+1,
5537 /* ea values, unlike ea
5540 } else if (buf_size == 0) {
5541 /* skip copy - calc size only */
5543 /* stop before overrun buffer */
5548 name_len -= temp_fea->name_len;
5549 temp_ptr += temp_fea->name_len;
5550 /* account for trailing null */
5553 name_len -= value_len;
5554 temp_ptr += value_len;
5555 /* No trailing null to account for in
5556 value_len. Go on to next EA */
5557 temp_fea = (struct fea *)temp_ptr;
5562 cifs_buf_release(pSMB);
5570 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5571 const char *ea_name, const void *ea_value,
5572 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5575 struct smb_com_transaction2_spi_req *pSMB = NULL;
5576 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5577 struct fealist *parm_data;
5580 int bytes_returned = 0;
5581 __u16 params, param_offset, byte_count, offset, count;
5583 cFYI(1, ("In SetEA"));
5585 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5590 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5592 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5593 PATH_MAX, nls_codepage, remap);
5594 name_len++; /* trailing null */
5596 } else { /* BB improve the check for buffer overruns BB */
5597 name_len = strnlen(fileName, PATH_MAX);
5598 name_len++; /* trailing null */
5599 strncpy(pSMB->FileName, fileName, name_len);
5602 params = 6 + name_len;
5604 /* done calculating parms using name_len of file name,
5605 now use name_len to calculate length of ea name
5606 we are going to create in the inode xattrs */
5607 if (ea_name == NULL)
5610 name_len = strnlen(ea_name, 255);
5612 count = sizeof(*parm_data) + ea_value_len + name_len;
5613 pSMB->MaxParameterCount = cpu_to_le16(2);
5614 /* BB find max SMB PDU from sess */
5615 pSMB->MaxDataCount = cpu_to_le16(1000);
5616 pSMB->MaxSetupCount = 0;
5620 pSMB->Reserved2 = 0;
5621 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5622 InformationLevel) - 4;
5623 offset = param_offset + params;
5624 pSMB->InformationLevel =
5625 cpu_to_le16(SMB_SET_FILE_EA);
5628 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5630 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5631 pSMB->DataOffset = cpu_to_le16(offset);
5632 pSMB->SetupCount = 1;
5633 pSMB->Reserved3 = 0;
5634 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5635 byte_count = 3 /* pad */ + params + count;
5636 pSMB->DataCount = cpu_to_le16(count);
5637 parm_data->list_len = cpu_to_le32(count);
5638 parm_data->list[0].EA_flags = 0;
5639 /* we checked above that name len is less than 255 */
5640 parm_data->list[0].name_len = (__u8)name_len;
5641 /* EA names are always ASCII */
5643 strncpy(parm_data->list[0].name, ea_name, name_len);
5644 parm_data->list[0].name[name_len] = 0;
5645 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5646 /* caller ensures that ea_value_len is less than 64K but
5647 we need to ensure that it fits within the smb */
5649 /*BB add length check to see if it would fit in
5650 negotiated SMB buffer size BB */
5651 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5653 memcpy(parm_data->list[0].name+name_len+1,
5654 ea_value, ea_value_len);
5656 pSMB->TotalDataCount = pSMB->DataCount;
5657 pSMB->ParameterCount = cpu_to_le16(params);
5658 pSMB->TotalParameterCount = pSMB->ParameterCount;
5659 pSMB->Reserved4 = 0;
5660 pSMB->hdr.smb_buf_length += byte_count;
5661 pSMB->ByteCount = cpu_to_le16(byte_count);
5662 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5663 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5665 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5667 cifs_buf_release(pSMB);