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 /* BB: do we need to check this? These should never be NULL. */
747 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
751 * No need to return error on this operation if tid invalidated and
752 * closed on server already e.g. due to tcp session crashing. Also,
753 * the tcon is no longer on the list, so no need to take lock before
756 if (tcon->need_reconnect)
759 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
760 (void **)&smb_buffer);
764 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
766 cFYI(1, ("Tree disconnect failed %d", rc));
768 /* No need to return error on this operation if tid invalidated and
769 closed on server already e.g. due to tcp session crashing */
777 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
779 LOGOFF_ANDX_REQ *pSMB;
782 cFYI(1, ("In SMBLogoff for session disconnect"));
785 * BB: do we need to check validity of ses and server? They should
786 * always be valid since we have an active reference. If not, that
787 * should probably be a BUG()
789 if (!ses || !ses->server)
793 if (ses->need_reconnect)
794 goto session_already_dead; /* no need to send SMBlogoff if uid
795 already closed due to reconnect */
796 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
802 pSMB->hdr.Mid = GetNextMid(ses->server);
804 if (ses->server->secMode &
805 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
806 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
808 pSMB->hdr.Uid = ses->Suid;
810 pSMB->AndXCommand = 0xFF;
811 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
812 session_already_dead:
815 /* if session dead then we do not need to do ulogoff,
816 since server closed smb session, no sense reporting
824 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
825 __u16 type, const struct nls_table *nls_codepage, int remap)
827 TRANSACTION2_SPI_REQ *pSMB = NULL;
828 TRANSACTION2_SPI_RSP *pSMBr = NULL;
829 struct unlink_psx_rq *pRqD;
832 int bytes_returned = 0;
833 __u16 params, param_offset, offset, byte_count;
835 cFYI(1, ("In POSIX delete"));
837 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
842 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
844 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
845 PATH_MAX, nls_codepage, remap);
846 name_len++; /* trailing null */
848 } else { /* BB add path length overrun check */
849 name_len = strnlen(fileName, PATH_MAX);
850 name_len++; /* trailing null */
851 strncpy(pSMB->FileName, fileName, name_len);
854 params = 6 + name_len;
855 pSMB->MaxParameterCount = cpu_to_le16(2);
856 pSMB->MaxDataCount = 0; /* BB double check this with jra */
857 pSMB->MaxSetupCount = 0;
862 param_offset = offsetof(struct smb_com_transaction2_spi_req,
863 InformationLevel) - 4;
864 offset = param_offset + params;
866 /* Setup pointer to Request Data (inode type) */
867 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
868 pRqD->type = cpu_to_le16(type);
869 pSMB->ParameterOffset = cpu_to_le16(param_offset);
870 pSMB->DataOffset = cpu_to_le16(offset);
871 pSMB->SetupCount = 1;
873 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
874 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
876 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
877 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878 pSMB->ParameterCount = cpu_to_le16(params);
879 pSMB->TotalParameterCount = pSMB->ParameterCount;
880 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
882 pSMB->hdr.smb_buf_length += byte_count;
883 pSMB->ByteCount = cpu_to_le16(byte_count);
884 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
885 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887 cFYI(1, ("Posix delete returned %d", rc));
888 cifs_buf_release(pSMB);
890 cifs_stats_inc(&tcon->num_deletes);
899 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
900 const struct nls_table *nls_codepage, int remap)
902 DELETE_FILE_REQ *pSMB = NULL;
903 DELETE_FILE_RSP *pSMBr = NULL;
909 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
914 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
916 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
917 PATH_MAX, nls_codepage, remap);
918 name_len++; /* trailing null */
920 } else { /* BB improve check for buffer overruns BB */
921 name_len = strnlen(fileName, PATH_MAX);
922 name_len++; /* trailing null */
923 strncpy(pSMB->fileName, fileName, name_len);
925 pSMB->SearchAttributes =
926 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
927 pSMB->BufferFormat = 0x04;
928 pSMB->hdr.smb_buf_length += name_len + 1;
929 pSMB->ByteCount = cpu_to_le16(name_len + 1);
930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
932 cifs_stats_inc(&tcon->num_deletes);
934 cFYI(1, ("Error in RMFile = %d", rc));
936 cifs_buf_release(pSMB);
944 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
945 const struct nls_table *nls_codepage, int remap)
947 DELETE_DIRECTORY_REQ *pSMB = NULL;
948 DELETE_DIRECTORY_RSP *pSMBr = NULL;
953 cFYI(1, ("In CIFSSMBRmDir"));
955 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
960 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
962 PATH_MAX, nls_codepage, remap);
963 name_len++; /* trailing null */
965 } else { /* BB improve check for buffer overruns BB */
966 name_len = strnlen(dirName, PATH_MAX);
967 name_len++; /* trailing null */
968 strncpy(pSMB->DirName, dirName, name_len);
971 pSMB->BufferFormat = 0x04;
972 pSMB->hdr.smb_buf_length += name_len + 1;
973 pSMB->ByteCount = cpu_to_le16(name_len + 1);
974 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
976 cifs_stats_inc(&tcon->num_rmdirs);
978 cFYI(1, ("Error in RMDir = %d", rc));
980 cifs_buf_release(pSMB);
987 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
988 const char *name, const struct nls_table *nls_codepage, int remap)
991 CREATE_DIRECTORY_REQ *pSMB = NULL;
992 CREATE_DIRECTORY_RSP *pSMBr = NULL;
996 cFYI(1, ("In CIFSSMBMkDir"));
998 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1003 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1004 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1005 PATH_MAX, nls_codepage, remap);
1006 name_len++; /* trailing null */
1008 } else { /* BB improve check for buffer overruns BB */
1009 name_len = strnlen(name, PATH_MAX);
1010 name_len++; /* trailing null */
1011 strncpy(pSMB->DirName, name, name_len);
1014 pSMB->BufferFormat = 0x04;
1015 pSMB->hdr.smb_buf_length += name_len + 1;
1016 pSMB->ByteCount = cpu_to_le16(name_len + 1);
1017 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1018 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1019 cifs_stats_inc(&tcon->num_mkdirs);
1021 cFYI(1, ("Error in Mkdir = %d", rc));
1023 cifs_buf_release(pSMB);
1030 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1031 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1032 __u32 *pOplock, const char *name,
1033 const struct nls_table *nls_codepage, int remap)
1035 TRANSACTION2_SPI_REQ *pSMB = NULL;
1036 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1039 int bytes_returned = 0;
1040 __u16 params, param_offset, offset, byte_count, count;
1041 OPEN_PSX_REQ *pdata;
1042 OPEN_PSX_RSP *psx_rsp;
1044 cFYI(1, ("In POSIX Create"));
1046 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1051 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1053 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1054 PATH_MAX, nls_codepage, remap);
1055 name_len++; /* trailing null */
1057 } else { /* BB improve the check for buffer overruns BB */
1058 name_len = strnlen(name, PATH_MAX);
1059 name_len++; /* trailing null */
1060 strncpy(pSMB->FileName, name, name_len);
1063 params = 6 + name_len;
1064 count = sizeof(OPEN_PSX_REQ);
1065 pSMB->MaxParameterCount = cpu_to_le16(2);
1066 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1067 pSMB->MaxSetupCount = 0;
1071 pSMB->Reserved2 = 0;
1072 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1073 InformationLevel) - 4;
1074 offset = param_offset + params;
1075 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1076 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1077 pdata->Permissions = cpu_to_le64(mode);
1078 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1079 pdata->OpenFlags = cpu_to_le32(*pOplock);
1080 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1081 pSMB->DataOffset = cpu_to_le16(offset);
1082 pSMB->SetupCount = 1;
1083 pSMB->Reserved3 = 0;
1084 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1085 byte_count = 3 /* pad */ + params + count;
1087 pSMB->DataCount = cpu_to_le16(count);
1088 pSMB->ParameterCount = cpu_to_le16(params);
1089 pSMB->TotalDataCount = pSMB->DataCount;
1090 pSMB->TotalParameterCount = pSMB->ParameterCount;
1091 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1092 pSMB->Reserved4 = 0;
1093 pSMB->hdr.smb_buf_length += byte_count;
1094 pSMB->ByteCount = cpu_to_le16(byte_count);
1095 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1096 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1098 cFYI(1, ("Posix create returned %d", rc));
1099 goto psx_create_err;
1102 cFYI(1, ("copying inode info"));
1103 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1105 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1106 rc = -EIO; /* bad smb */
1107 goto psx_create_err;
1110 /* copy return information to pRetData */
1111 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1112 + le16_to_cpu(pSMBr->t2.DataOffset));
1114 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1116 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1117 /* Let caller know file was created so we can set the mode. */
1118 /* Do we care about the CreateAction in any other cases? */
1119 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1120 *pOplock |= CIFS_CREATE_ACTION;
1121 /* check to make sure response data is there */
1122 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1123 pRetData->Type = cpu_to_le32(-1); /* unknown */
1124 cFYI(DBG2, ("unknown type"));
1126 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1127 + sizeof(FILE_UNIX_BASIC_INFO)) {
1128 cERROR(1, ("Open response data too small"));
1129 pRetData->Type = cpu_to_le32(-1);
1130 goto psx_create_err;
1132 memcpy((char *) pRetData,
1133 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1134 sizeof(FILE_UNIX_BASIC_INFO));
1138 cifs_buf_release(pSMB);
1140 cifs_stats_inc(&tcon->num_mkdirs);
1148 static __u16 convert_disposition(int disposition)
1152 switch (disposition) {
1153 case FILE_SUPERSEDE:
1154 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1157 ofun = SMBOPEN_OAPPEND;
1160 ofun = SMBOPEN_OCREATE;
1163 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1165 case FILE_OVERWRITE:
1166 ofun = SMBOPEN_OTRUNC;
1168 case FILE_OVERWRITE_IF:
1169 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1172 cFYI(1, ("unknown disposition %d", disposition));
1173 ofun = SMBOPEN_OAPPEND; /* regular open */
1179 access_flags_to_smbopen_mode(const int access_flags)
1181 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1183 if (masked_flags == GENERIC_READ)
1184 return SMBOPEN_READ;
1185 else if (masked_flags == GENERIC_WRITE)
1186 return SMBOPEN_WRITE;
1188 /* just go for read/write */
1189 return SMBOPEN_READWRITE;
1193 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1194 const char *fileName, const int openDisposition,
1195 const int access_flags, const int create_options, __u16 *netfid,
1196 int *pOplock, FILE_ALL_INFO *pfile_info,
1197 const struct nls_table *nls_codepage, int remap)
1200 OPENX_REQ *pSMB = NULL;
1201 OPENX_RSP *pSMBr = NULL;
1207 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1212 pSMB->AndXCommand = 0xFF; /* none */
1214 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1215 count = 1; /* account for one byte pad to word boundary */
1217 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1218 fileName, PATH_MAX, nls_codepage, remap);
1219 name_len++; /* trailing null */
1221 } else { /* BB improve check for buffer overruns BB */
1222 count = 0; /* no pad */
1223 name_len = strnlen(fileName, PATH_MAX);
1224 name_len++; /* trailing null */
1225 strncpy(pSMB->fileName, fileName, name_len);
1227 if (*pOplock & REQ_OPLOCK)
1228 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1229 else if (*pOplock & REQ_BATCHOPLOCK)
1230 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1232 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1233 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1234 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1235 /* set file as system file if special file such
1236 as fifo and server expecting SFU style and
1237 no Unix extensions */
1239 if (create_options & CREATE_OPTION_SPECIAL)
1240 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1241 else /* BB FIXME BB */
1242 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1244 if (create_options & CREATE_OPTION_READONLY)
1245 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1248 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1249 CREATE_OPTIONS_MASK); */
1250 /* BB FIXME END BB */
1252 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1253 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1255 pSMB->hdr.smb_buf_length += count;
1257 pSMB->ByteCount = cpu_to_le16(count);
1258 /* long_op set to 1 to allow for oplock break timeouts */
1259 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1260 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1261 cifs_stats_inc(&tcon->num_opens);
1263 cFYI(1, ("Error in Open = %d", rc));
1265 /* BB verify if wct == 15 */
1267 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1269 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1270 /* Let caller know file was created so we can set the mode. */
1271 /* Do we care about the CreateAction in any other cases? */
1273 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1274 *pOplock |= CIFS_CREATE_ACTION; */
1278 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1279 pfile_info->LastAccessTime = 0; /* BB fixme */
1280 pfile_info->LastWriteTime = 0; /* BB fixme */
1281 pfile_info->ChangeTime = 0; /* BB fixme */
1282 pfile_info->Attributes =
1283 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1284 /* the file_info buf is endian converted by caller */
1285 pfile_info->AllocationSize =
1286 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1287 pfile_info->EndOfFile = pfile_info->AllocationSize;
1288 pfile_info->NumberOfLinks = cpu_to_le32(1);
1289 pfile_info->DeletePending = 0;
1293 cifs_buf_release(pSMB);
1300 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1301 const char *fileName, const int openDisposition,
1302 const int access_flags, const int create_options, __u16 *netfid,
1303 int *pOplock, FILE_ALL_INFO *pfile_info,
1304 const struct nls_table *nls_codepage, int remap)
1307 OPEN_REQ *pSMB = NULL;
1308 OPEN_RSP *pSMBr = NULL;
1314 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1319 pSMB->AndXCommand = 0xFF; /* none */
1321 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1322 count = 1; /* account for one byte pad to word boundary */
1324 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1325 fileName, PATH_MAX, nls_codepage, remap);
1326 name_len++; /* trailing null */
1328 pSMB->NameLength = cpu_to_le16(name_len);
1329 } else { /* BB improve check for buffer overruns BB */
1330 count = 0; /* no pad */
1331 name_len = strnlen(fileName, PATH_MAX);
1332 name_len++; /* trailing null */
1333 pSMB->NameLength = cpu_to_le16(name_len);
1334 strncpy(pSMB->fileName, fileName, name_len);
1336 if (*pOplock & REQ_OPLOCK)
1337 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1338 else if (*pOplock & REQ_BATCHOPLOCK)
1339 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1340 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1341 pSMB->AllocationSize = 0;
1342 /* set file as system file if special file such
1343 as fifo and server expecting SFU style and
1344 no Unix extensions */
1345 if (create_options & CREATE_OPTION_SPECIAL)
1346 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1348 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1350 /* XP does not handle ATTR_POSIX_SEMANTICS */
1351 /* but it helps speed up case sensitive checks for other
1352 servers such as Samba */
1353 if (tcon->ses->capabilities & CAP_UNIX)
1354 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1356 if (create_options & CREATE_OPTION_READONLY)
1357 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1359 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1360 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1361 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1362 /* BB Expirement with various impersonation levels and verify */
1363 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1364 pSMB->SecurityFlags =
1365 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1368 pSMB->hdr.smb_buf_length += count;
1370 pSMB->ByteCount = cpu_to_le16(count);
1371 /* long_op set to 1 to allow for oplock break timeouts */
1372 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1373 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1374 cifs_stats_inc(&tcon->num_opens);
1376 cFYI(1, ("Error in Open = %d", rc));
1378 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1379 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1380 /* Let caller know file was created so we can set the mode. */
1381 /* Do we care about the CreateAction in any other cases? */
1382 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1383 *pOplock |= CIFS_CREATE_ACTION;
1385 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1386 36 /* CreationTime to Attributes */);
1387 /* the file_info buf is endian converted by caller */
1388 pfile_info->AllocationSize = pSMBr->AllocationSize;
1389 pfile_info->EndOfFile = pSMBr->EndOfFile;
1390 pfile_info->NumberOfLinks = cpu_to_le32(1);
1391 pfile_info->DeletePending = 0;
1395 cifs_buf_release(pSMB);
1402 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1403 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1404 char **buf, int *pbuf_type)
1407 READ_REQ *pSMB = NULL;
1408 READ_RSP *pSMBr = NULL;
1409 char *pReadData = NULL;
1411 int resp_buf_type = 0;
1414 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1415 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1418 wct = 10; /* old style read */
1421 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1425 /* tcon and ses pointer are checked in smb_init */
1426 if (tcon->ses->server == NULL)
1427 return -ECONNABORTED;
1429 pSMB->AndXCommand = 0xFF; /* none */
1431 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1433 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1434 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1437 pSMB->Remaining = 0;
1438 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1439 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1441 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1443 /* old style read */
1444 struct smb_com_readx_req *pSMBW =
1445 (struct smb_com_readx_req *)pSMB;
1446 pSMBW->ByteCount = 0;
1449 iov[0].iov_base = (char *)pSMB;
1450 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1451 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1452 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1453 cifs_stats_inc(&tcon->num_reads);
1454 pSMBr = (READ_RSP *)iov[0].iov_base;
1456 cERROR(1, ("Send error in read = %d", rc));
1458 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1459 data_length = data_length << 16;
1460 data_length += le16_to_cpu(pSMBr->DataLength);
1461 *nbytes = data_length;
1463 /*check that DataLength would not go beyond end of SMB */
1464 if ((data_length > CIFSMaxBufSize)
1465 || (data_length > count)) {
1466 cFYI(1, ("bad length %d for count %d",
1467 data_length, count));
1471 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1472 le16_to_cpu(pSMBr->DataOffset);
1473 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1474 cERROR(1,("Faulting on read rc = %d",rc));
1476 }*/ /* can not use copy_to_user when using page cache*/
1478 memcpy(*buf, pReadData, data_length);
1482 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1484 if (resp_buf_type == CIFS_SMALL_BUFFER)
1485 cifs_small_buf_release(iov[0].iov_base);
1486 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1487 cifs_buf_release(iov[0].iov_base);
1488 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1489 /* return buffer to caller to free */
1490 *buf = iov[0].iov_base;
1491 if (resp_buf_type == CIFS_SMALL_BUFFER)
1492 *pbuf_type = CIFS_SMALL_BUFFER;
1493 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1494 *pbuf_type = CIFS_LARGE_BUFFER;
1495 } /* else no valid buffer on return - leave as null */
1497 /* Note: On -EAGAIN error only caller can retry on handle based calls
1498 since file handle passed in no longer valid */
1504 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1505 const int netfid, const unsigned int count,
1506 const __u64 offset, unsigned int *nbytes, const char *buf,
1507 const char __user *ubuf, const int long_op)
1510 WRITE_REQ *pSMB = NULL;
1511 WRITE_RSP *pSMBr = NULL;
1512 int bytes_returned, wct;
1516 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1517 if (tcon->ses == NULL)
1518 return -ECONNABORTED;
1520 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1525 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1529 /* tcon and ses pointer are checked in smb_init */
1530 if (tcon->ses->server == NULL)
1531 return -ECONNABORTED;
1533 pSMB->AndXCommand = 0xFF; /* none */
1535 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1537 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1538 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1541 pSMB->Reserved = 0xFFFFFFFF;
1542 pSMB->WriteMode = 0;
1543 pSMB->Remaining = 0;
1545 /* Can increase buffer size if buffer is big enough in some cases ie we
1546 can send more if LARGE_WRITE_X capability returned by the server and if
1547 our buffer is big enough or if we convert to iovecs on socket writes
1548 and eliminate the copy to the CIFS buffer */
1549 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1550 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1552 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1556 if (bytes_sent > count)
1559 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1561 memcpy(pSMB->Data, buf, bytes_sent);
1563 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1564 cifs_buf_release(pSMB);
1567 } else if (count != 0) {
1569 cifs_buf_release(pSMB);
1571 } /* else setting file size with write of zero bytes */
1573 byte_count = bytes_sent + 1; /* pad */
1574 else /* wct == 12 */
1575 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1577 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1578 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1579 pSMB->hdr.smb_buf_length += byte_count;
1582 pSMB->ByteCount = cpu_to_le16(byte_count);
1583 else { /* old style write has byte count 4 bytes earlier
1585 struct smb_com_writex_req *pSMBW =
1586 (struct smb_com_writex_req *)pSMB;
1587 pSMBW->ByteCount = cpu_to_le16(byte_count);
1590 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1591 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1592 cifs_stats_inc(&tcon->num_writes);
1594 cFYI(1, ("Send error in write = %d", rc));
1597 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1598 *nbytes = (*nbytes) << 16;
1599 *nbytes += le16_to_cpu(pSMBr->Count);
1602 cifs_buf_release(pSMB);
1604 /* Note: On -EAGAIN error only caller can retry on handle based calls
1605 since file handle passed in no longer valid */
1611 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1612 const int netfid, const unsigned int count,
1613 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1614 int n_vec, const int long_op)
1617 WRITE_REQ *pSMB = NULL;
1620 int resp_buf_type = 0;
1622 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1624 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1628 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1631 /* tcon and ses pointer are checked in smb_init */
1632 if (tcon->ses->server == NULL)
1633 return -ECONNABORTED;
1635 pSMB->AndXCommand = 0xFF; /* none */
1637 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1639 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1640 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1642 pSMB->Reserved = 0xFFFFFFFF;
1643 pSMB->WriteMode = 0;
1644 pSMB->Remaining = 0;
1647 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1649 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1650 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1651 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1653 pSMB->hdr.smb_buf_length += count+1;
1654 else /* wct == 12 */
1655 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1657 pSMB->ByteCount = cpu_to_le16(count + 1);
1658 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1659 struct smb_com_writex_req *pSMBW =
1660 (struct smb_com_writex_req *)pSMB;
1661 pSMBW->ByteCount = cpu_to_le16(count + 5);
1663 iov[0].iov_base = pSMB;
1665 iov[0].iov_len = smb_hdr_len + 4;
1666 else /* wct == 12 pad bigger by four bytes */
1667 iov[0].iov_len = smb_hdr_len + 8;
1670 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1672 cifs_stats_inc(&tcon->num_writes);
1674 cFYI(1, ("Send error Write2 = %d", rc));
1676 } else if (resp_buf_type == 0) {
1677 /* presumably this can not happen, but best to be safe */
1681 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1682 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1683 *nbytes = (*nbytes) << 16;
1684 *nbytes += le16_to_cpu(pSMBr->Count);
1687 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1688 if (resp_buf_type == CIFS_SMALL_BUFFER)
1689 cifs_small_buf_release(iov[0].iov_base);
1690 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1691 cifs_buf_release(iov[0].iov_base);
1693 /* Note: On -EAGAIN error only caller can retry on handle based calls
1694 since file handle passed in no longer valid */
1701 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1702 const __u16 smb_file_id, const __u64 len,
1703 const __u64 offset, const __u32 numUnlock,
1704 const __u32 numLock, const __u8 lockType, const bool waitFlag)
1707 LOCK_REQ *pSMB = NULL;
1708 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1713 cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1714 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1719 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1720 timeout = CIFS_ASYNC_OP; /* no response expected */
1722 } else if (waitFlag) {
1723 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1724 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1729 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1730 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1731 pSMB->LockType = lockType;
1732 pSMB->AndXCommand = 0xFF; /* none */
1733 pSMB->Fid = smb_file_id; /* netfid stays le */
1735 if ((numLock != 0) || (numUnlock != 0)) {
1736 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1737 /* BB where to store pid high? */
1738 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1739 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1740 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1741 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1742 count = sizeof(LOCKING_ANDX_RANGE);
1747 pSMB->hdr.smb_buf_length += count;
1748 pSMB->ByteCount = cpu_to_le16(count);
1751 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1752 (struct smb_hdr *) pSMB, &bytes_returned);
1753 cifs_small_buf_release(pSMB);
1755 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1757 /* SMB buffer freed by function above */
1759 cifs_stats_inc(&tcon->num_locks);
1761 cFYI(1, ("Send error in Lock = %d", rc));
1763 /* Note: On -EAGAIN error only caller can retry on handle based calls
1764 since file handle passed in no longer valid */
1769 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1770 const __u16 smb_file_id, const int get_flag, const __u64 len,
1771 struct file_lock *pLockData, const __u16 lock_type,
1772 const bool waitFlag)
1774 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1775 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1776 struct cifs_posix_lock *parm_data;
1779 int bytes_returned = 0;
1780 int resp_buf_type = 0;
1781 __u16 params, param_offset, offset, byte_count, count;
1784 cFYI(1, ("Posix Lock"));
1786 if (pLockData == NULL)
1789 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1794 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1797 pSMB->MaxSetupCount = 0;
1800 pSMB->Reserved2 = 0;
1801 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1802 offset = param_offset + params;
1804 count = sizeof(struct cifs_posix_lock);
1805 pSMB->MaxParameterCount = cpu_to_le16(2);
1806 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1807 pSMB->SetupCount = 1;
1808 pSMB->Reserved3 = 0;
1810 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1812 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1813 byte_count = 3 /* pad */ + params + count;
1814 pSMB->DataCount = cpu_to_le16(count);
1815 pSMB->ParameterCount = cpu_to_le16(params);
1816 pSMB->TotalDataCount = pSMB->DataCount;
1817 pSMB->TotalParameterCount = pSMB->ParameterCount;
1818 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1819 parm_data = (struct cifs_posix_lock *)
1820 (((char *) &pSMB->hdr.Protocol) + offset);
1822 parm_data->lock_type = cpu_to_le16(lock_type);
1824 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1825 parm_data->lock_flags = cpu_to_le16(1);
1826 pSMB->Timeout = cpu_to_le32(-1);
1830 parm_data->pid = cpu_to_le32(current->tgid);
1831 parm_data->start = cpu_to_le64(pLockData->fl_start);
1832 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1834 pSMB->DataOffset = cpu_to_le16(offset);
1835 pSMB->Fid = smb_file_id;
1836 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1837 pSMB->Reserved4 = 0;
1838 pSMB->hdr.smb_buf_length += byte_count;
1839 pSMB->ByteCount = cpu_to_le16(byte_count);
1841 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1842 (struct smb_hdr *) pSMBr, &bytes_returned);
1844 iov[0].iov_base = (char *)pSMB;
1845 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1846 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1847 &resp_buf_type, timeout);
1848 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1849 not try to free it twice below on exit */
1850 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1854 cFYI(1, ("Send error in Posix Lock = %d", rc));
1855 } else if (get_flag) {
1856 /* lock structure can be returned on get */
1859 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1861 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1862 rc = -EIO; /* bad smb */
1865 if (pLockData == NULL) {
1869 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1870 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1871 if (data_count < sizeof(struct cifs_posix_lock)) {
1875 parm_data = (struct cifs_posix_lock *)
1876 ((char *)&pSMBr->hdr.Protocol + data_offset);
1877 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1878 pLockData->fl_type = F_UNLCK;
1883 cifs_small_buf_release(pSMB);
1885 if (resp_buf_type == CIFS_SMALL_BUFFER)
1886 cifs_small_buf_release(iov[0].iov_base);
1887 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1888 cifs_buf_release(iov[0].iov_base);
1890 /* Note: On -EAGAIN error only caller can retry on handle based calls
1891 since file handle passed in no longer valid */
1898 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1901 CLOSE_REQ *pSMB = NULL;
1902 cFYI(1, ("In CIFSSMBClose"));
1904 /* do not retry on dead session on close */
1905 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1911 pSMB->FileID = (__u16) smb_file_id;
1912 pSMB->LastWriteTime = 0xFFFFFFFF;
1913 pSMB->ByteCount = 0;
1914 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1915 cifs_stats_inc(&tcon->num_closes);
1918 /* EINTR is expected when user ctl-c to kill app */
1919 cERROR(1, ("Send error in Close = %d", rc));
1923 /* Since session is dead, file will be closed on server already */
1931 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1932 const char *fromName, const char *toName,
1933 const struct nls_table *nls_codepage, int remap)
1936 RENAME_REQ *pSMB = NULL;
1937 RENAME_RSP *pSMBr = NULL;
1939 int name_len, name_len2;
1942 cFYI(1, ("In CIFSSMBRename"));
1944 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1949 pSMB->BufferFormat = 0x04;
1950 pSMB->SearchAttributes =
1951 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1956 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1957 PATH_MAX, nls_codepage, remap);
1958 name_len++; /* trailing null */
1960 pSMB->OldFileName[name_len] = 0x04; /* pad */
1961 /* protocol requires ASCII signature byte on Unicode string */
1962 pSMB->OldFileName[name_len + 1] = 0x00;
1964 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1965 toName, PATH_MAX, nls_codepage, remap);
1966 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1967 name_len2 *= 2; /* convert to bytes */
1968 } else { /* BB improve the check for buffer overruns BB */
1969 name_len = strnlen(fromName, PATH_MAX);
1970 name_len++; /* trailing null */
1971 strncpy(pSMB->OldFileName, fromName, name_len);
1972 name_len2 = strnlen(toName, PATH_MAX);
1973 name_len2++; /* trailing null */
1974 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1975 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1976 name_len2++; /* trailing null */
1977 name_len2++; /* signature byte */
1980 count = 1 /* 1st signature byte */ + name_len + name_len2;
1981 pSMB->hdr.smb_buf_length += count;
1982 pSMB->ByteCount = cpu_to_le16(count);
1984 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1985 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1986 cifs_stats_inc(&tcon->num_renames);
1988 cFYI(1, ("Send error in rename = %d", rc));
1990 cifs_buf_release(pSMB);
1998 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1999 int netfid, const char *target_name,
2000 const struct nls_table *nls_codepage, int remap)
2002 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2003 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2004 struct set_file_rename *rename_info;
2006 char dummy_string[30];
2008 int bytes_returned = 0;
2010 __u16 params, param_offset, offset, count, byte_count;
2012 cFYI(1, ("Rename to File by handle"));
2013 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2019 pSMB->MaxSetupCount = 0;
2023 pSMB->Reserved2 = 0;
2024 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2025 offset = param_offset + params;
2027 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2028 rename_info = (struct set_file_rename *) data_offset;
2029 pSMB->MaxParameterCount = cpu_to_le16(2);
2030 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2031 pSMB->SetupCount = 1;
2032 pSMB->Reserved3 = 0;
2033 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2034 byte_count = 3 /* pad */ + params;
2035 pSMB->ParameterCount = cpu_to_le16(params);
2036 pSMB->TotalParameterCount = pSMB->ParameterCount;
2037 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2038 pSMB->DataOffset = cpu_to_le16(offset);
2039 /* construct random name ".cifs_tmp<inodenum><mid>" */
2040 rename_info->overwrite = cpu_to_le32(1);
2041 rename_info->root_fid = 0;
2042 /* unicode only call */
2043 if (target_name == NULL) {
2044 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2045 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2046 dummy_string, 24, nls_codepage, remap);
2048 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2049 target_name, PATH_MAX, nls_codepage,
2052 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2053 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2054 byte_count += count;
2055 pSMB->DataCount = cpu_to_le16(count);
2056 pSMB->TotalDataCount = pSMB->DataCount;
2058 pSMB->InformationLevel =
2059 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2060 pSMB->Reserved4 = 0;
2061 pSMB->hdr.smb_buf_length += byte_count;
2062 pSMB->ByteCount = cpu_to_le16(byte_count);
2063 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2064 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2065 cifs_stats_inc(&pTcon->num_t2renames);
2067 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2069 cifs_buf_release(pSMB);
2071 /* Note: On -EAGAIN error only caller can retry on handle based calls
2072 since file handle passed in no longer valid */
2078 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2079 const __u16 target_tid, const char *toName, const int flags,
2080 const struct nls_table *nls_codepage, int remap)
2083 COPY_REQ *pSMB = NULL;
2084 COPY_RSP *pSMBr = NULL;
2086 int name_len, name_len2;
2089 cFYI(1, ("In CIFSSMBCopy"));
2091 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2096 pSMB->BufferFormat = 0x04;
2097 pSMB->Tid2 = target_tid;
2099 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2101 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2102 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2103 fromName, PATH_MAX, nls_codepage,
2105 name_len++; /* trailing null */
2107 pSMB->OldFileName[name_len] = 0x04; /* pad */
2108 /* protocol requires ASCII signature byte on Unicode string */
2109 pSMB->OldFileName[name_len + 1] = 0x00;
2111 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2112 toName, PATH_MAX, nls_codepage, remap);
2113 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2114 name_len2 *= 2; /* convert to bytes */
2115 } else { /* BB improve the check for buffer overruns BB */
2116 name_len = strnlen(fromName, PATH_MAX);
2117 name_len++; /* trailing null */
2118 strncpy(pSMB->OldFileName, fromName, name_len);
2119 name_len2 = strnlen(toName, PATH_MAX);
2120 name_len2++; /* trailing null */
2121 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2122 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2123 name_len2++; /* trailing null */
2124 name_len2++; /* signature byte */
2127 count = 1 /* 1st signature byte */ + name_len + name_len2;
2128 pSMB->hdr.smb_buf_length += count;
2129 pSMB->ByteCount = cpu_to_le16(count);
2131 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2132 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2134 cFYI(1, ("Send error in copy = %d with %d files copied",
2135 rc, le16_to_cpu(pSMBr->CopyCount)));
2137 cifs_buf_release(pSMB);
2146 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2147 const char *fromName, const char *toName,
2148 const struct nls_table *nls_codepage)
2150 TRANSACTION2_SPI_REQ *pSMB = NULL;
2151 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2154 int name_len_target;
2156 int bytes_returned = 0;
2157 __u16 params, param_offset, offset, byte_count;
2159 cFYI(1, ("In Symlink Unix style"));
2161 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2166 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2168 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2169 /* find define for this maxpathcomponent */
2171 name_len++; /* trailing null */
2174 } else { /* BB improve the check for buffer overruns BB */
2175 name_len = strnlen(fromName, PATH_MAX);
2176 name_len++; /* trailing null */
2177 strncpy(pSMB->FileName, fromName, name_len);
2179 params = 6 + name_len;
2180 pSMB->MaxSetupCount = 0;
2184 pSMB->Reserved2 = 0;
2185 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2186 InformationLevel) - 4;
2187 offset = param_offset + params;
2189 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2190 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2192 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2193 /* find define for this maxpathcomponent */
2195 name_len_target++; /* trailing null */
2196 name_len_target *= 2;
2197 } else { /* BB improve the check for buffer overruns BB */
2198 name_len_target = strnlen(toName, PATH_MAX);
2199 name_len_target++; /* trailing null */
2200 strncpy(data_offset, toName, name_len_target);
2203 pSMB->MaxParameterCount = cpu_to_le16(2);
2204 /* BB find exact max on data count below from sess */
2205 pSMB->MaxDataCount = cpu_to_le16(1000);
2206 pSMB->SetupCount = 1;
2207 pSMB->Reserved3 = 0;
2208 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2209 byte_count = 3 /* pad */ + params + name_len_target;
2210 pSMB->DataCount = cpu_to_le16(name_len_target);
2211 pSMB->ParameterCount = cpu_to_le16(params);
2212 pSMB->TotalDataCount = pSMB->DataCount;
2213 pSMB->TotalParameterCount = pSMB->ParameterCount;
2214 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2215 pSMB->DataOffset = cpu_to_le16(offset);
2216 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2217 pSMB->Reserved4 = 0;
2218 pSMB->hdr.smb_buf_length += byte_count;
2219 pSMB->ByteCount = cpu_to_le16(byte_count);
2220 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2221 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2222 cifs_stats_inc(&tcon->num_symlinks);
2224 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2226 cifs_buf_release(pSMB);
2229 goto createSymLinkRetry;
2235 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2236 const char *fromName, const char *toName,
2237 const struct nls_table *nls_codepage, int remap)
2239 TRANSACTION2_SPI_REQ *pSMB = NULL;
2240 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2243 int name_len_target;
2245 int bytes_returned = 0;
2246 __u16 params, param_offset, offset, byte_count;
2248 cFYI(1, ("In Create Hard link Unix style"));
2249 createHardLinkRetry:
2250 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2255 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2256 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2257 PATH_MAX, nls_codepage, remap);
2258 name_len++; /* trailing null */
2261 } else { /* BB improve the check for buffer overruns BB */
2262 name_len = strnlen(toName, PATH_MAX);
2263 name_len++; /* trailing null */
2264 strncpy(pSMB->FileName, toName, name_len);
2266 params = 6 + name_len;
2267 pSMB->MaxSetupCount = 0;
2271 pSMB->Reserved2 = 0;
2272 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2273 InformationLevel) - 4;
2274 offset = param_offset + params;
2276 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2279 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2280 nls_codepage, remap);
2281 name_len_target++; /* trailing null */
2282 name_len_target *= 2;
2283 } else { /* BB improve the check for buffer overruns BB */
2284 name_len_target = strnlen(fromName, PATH_MAX);
2285 name_len_target++; /* trailing null */
2286 strncpy(data_offset, fromName, name_len_target);
2289 pSMB->MaxParameterCount = cpu_to_le16(2);
2290 /* BB find exact max on data count below from sess*/
2291 pSMB->MaxDataCount = cpu_to_le16(1000);
2292 pSMB->SetupCount = 1;
2293 pSMB->Reserved3 = 0;
2294 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2295 byte_count = 3 /* pad */ + params + name_len_target;
2296 pSMB->ParameterCount = cpu_to_le16(params);
2297 pSMB->TotalParameterCount = pSMB->ParameterCount;
2298 pSMB->DataCount = cpu_to_le16(name_len_target);
2299 pSMB->TotalDataCount = pSMB->DataCount;
2300 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2301 pSMB->DataOffset = cpu_to_le16(offset);
2302 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2303 pSMB->Reserved4 = 0;
2304 pSMB->hdr.smb_buf_length += byte_count;
2305 pSMB->ByteCount = cpu_to_le16(byte_count);
2306 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2307 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2308 cifs_stats_inc(&tcon->num_hardlinks);
2310 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2312 cifs_buf_release(pSMB);
2314 goto createHardLinkRetry;
2320 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2321 const char *fromName, const char *toName,
2322 const struct nls_table *nls_codepage, int remap)
2325 NT_RENAME_REQ *pSMB = NULL;
2326 RENAME_RSP *pSMBr = NULL;
2328 int name_len, name_len2;
2331 cFYI(1, ("In CIFSCreateHardLink"));
2332 winCreateHardLinkRetry:
2334 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2339 pSMB->SearchAttributes =
2340 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2342 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2343 pSMB->ClusterCount = 0;
2345 pSMB->BufferFormat = 0x04;
2347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2349 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2350 PATH_MAX, nls_codepage, remap);
2351 name_len++; /* trailing null */
2353 pSMB->OldFileName[name_len] = 0; /* pad */
2354 pSMB->OldFileName[name_len + 1] = 0x04;
2356 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2357 toName, PATH_MAX, nls_codepage, remap);
2358 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2359 name_len2 *= 2; /* convert to bytes */
2360 } else { /* BB improve the check for buffer overruns BB */
2361 name_len = strnlen(fromName, PATH_MAX);
2362 name_len++; /* trailing null */
2363 strncpy(pSMB->OldFileName, fromName, name_len);
2364 name_len2 = strnlen(toName, PATH_MAX);
2365 name_len2++; /* trailing null */
2366 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2367 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2368 name_len2++; /* trailing null */
2369 name_len2++; /* signature byte */
2372 count = 1 /* string type byte */ + name_len + name_len2;
2373 pSMB->hdr.smb_buf_length += count;
2374 pSMB->ByteCount = cpu_to_le16(count);
2376 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2377 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2378 cifs_stats_inc(&tcon->num_hardlinks);
2380 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2382 cifs_buf_release(pSMB);
2384 goto winCreateHardLinkRetry;
2390 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2391 const unsigned char *searchName,
2392 char *symlinkinfo, const int buflen,
2393 const struct nls_table *nls_codepage)
2395 /* SMB_QUERY_FILE_UNIX_LINK */
2396 TRANSACTION2_QPI_REQ *pSMB = NULL;
2397 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2401 __u16 params, byte_count;
2403 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2406 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2411 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2413 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2414 PATH_MAX, nls_codepage);
2415 name_len++; /* trailing null */
2417 } else { /* BB improve the check for buffer overruns BB */
2418 name_len = strnlen(searchName, PATH_MAX);
2419 name_len++; /* trailing null */
2420 strncpy(pSMB->FileName, searchName, name_len);
2423 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2424 pSMB->TotalDataCount = 0;
2425 pSMB->MaxParameterCount = cpu_to_le16(2);
2426 /* BB find exact max data count below from sess structure BB */
2427 pSMB->MaxDataCount = cpu_to_le16(4000);
2428 pSMB->MaxSetupCount = 0;
2432 pSMB->Reserved2 = 0;
2433 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2434 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2435 pSMB->DataCount = 0;
2436 pSMB->DataOffset = 0;
2437 pSMB->SetupCount = 1;
2438 pSMB->Reserved3 = 0;
2439 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2440 byte_count = params + 1 /* pad */ ;
2441 pSMB->TotalParameterCount = cpu_to_le16(params);
2442 pSMB->ParameterCount = pSMB->TotalParameterCount;
2443 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2444 pSMB->Reserved4 = 0;
2445 pSMB->hdr.smb_buf_length += byte_count;
2446 pSMB->ByteCount = cpu_to_le16(byte_count);
2448 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2449 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2451 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2453 /* decode response */
2455 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2456 if (rc || (pSMBr->ByteCount < 2))
2457 /* BB also check enough total bytes returned */
2458 rc = -EIO; /* bad smb */
2460 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2461 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2463 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2464 name_len = UniStrnlen((wchar_t *) ((char *)
2465 &pSMBr->hdr.Protocol + data_offset),
2466 min_t(const int, buflen, count) / 2);
2467 /* BB FIXME investigate remapping reserved chars here */
2468 cifs_strfromUCS_le(symlinkinfo,
2469 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2471 name_len, nls_codepage);
2473 strncpy(symlinkinfo,
2474 (char *) &pSMBr->hdr.Protocol +
2476 min_t(const int, buflen, count));
2478 symlinkinfo[buflen] = 0;
2479 /* just in case so calling code does not go off the end of buffer */
2482 cifs_buf_release(pSMB);
2484 goto querySymLinkRetry;
2488 #ifdef CONFIG_CIFS_EXPERIMENTAL
2489 /* Initialize NT TRANSACT SMB into small smb request buffer.
2490 This assumes that all NT TRANSACTS that we init here have
2491 total parm and data under about 400 bytes (to fit in small cifs
2492 buffer size), which is the case so far, it easily fits. NB:
2493 Setup words themselves and ByteCount
2494 MaxSetupCount (size of returned setup area) and
2495 MaxParameterCount (returned parms size) must be set by caller */
2497 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2498 const int parm_len, struct cifsTconInfo *tcon,
2503 struct smb_com_ntransact_req *pSMB;
2505 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2509 *ret_buf = (void *)pSMB;
2511 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2512 pSMB->TotalDataCount = 0;
2513 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2514 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2515 pSMB->ParameterCount = pSMB->TotalParameterCount;
2516 pSMB->DataCount = pSMB->TotalDataCount;
2517 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2518 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2519 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2520 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2521 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2522 pSMB->SubCommand = cpu_to_le16(sub_command);
2527 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2528 __u32 *pparmlen, __u32 *pdatalen)
2531 __u32 data_count, data_offset, parm_count, parm_offset;
2532 struct smb_com_ntransact_rsp *pSMBr;
2540 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2542 /* ByteCount was converted from little endian in SendReceive */
2543 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2544 (char *)&pSMBr->ByteCount;
2546 data_offset = le32_to_cpu(pSMBr->DataOffset);
2547 data_count = le32_to_cpu(pSMBr->DataCount);
2548 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2549 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2551 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2552 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2554 /* should we also check that parm and data areas do not overlap? */
2555 if (*ppparm > end_of_smb) {
2556 cFYI(1, ("parms start after end of smb"));
2558 } else if (parm_count + *ppparm > end_of_smb) {
2559 cFYI(1, ("parm end after end of smb"));
2561 } else if (*ppdata > end_of_smb) {
2562 cFYI(1, ("data starts after end of smb"));
2564 } else if (data_count + *ppdata > end_of_smb) {
2565 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2566 *ppdata, data_count, (data_count + *ppdata),
2567 end_of_smb, pSMBr));
2569 } else if (parm_count + data_count > pSMBr->ByteCount) {
2570 cFYI(1, ("parm count and data count larger than SMB"));
2573 *pdatalen = data_count;
2574 *pparmlen = parm_count;
2577 #endif /* CIFS_EXPERIMENTAL */
2580 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2581 const unsigned char *searchName,
2582 char *symlinkinfo, const int buflen, __u16 fid,
2583 const struct nls_table *nls_codepage)
2588 struct smb_com_transaction_ioctl_req *pSMB;
2589 struct smb_com_transaction_ioctl_rsp *pSMBr;
2591 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2592 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2597 pSMB->TotalParameterCount = 0 ;
2598 pSMB->TotalDataCount = 0;
2599 pSMB->MaxParameterCount = cpu_to_le32(2);
2600 /* BB find exact data count max from sess structure BB */
2601 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2602 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2603 pSMB->MaxSetupCount = 4;
2605 pSMB->ParameterOffset = 0;
2606 pSMB->DataCount = 0;
2607 pSMB->DataOffset = 0;
2608 pSMB->SetupCount = 4;
2609 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2610 pSMB->ParameterCount = pSMB->TotalParameterCount;
2611 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2612 pSMB->IsFsctl = 1; /* FSCTL */
2613 pSMB->IsRootFlag = 0;
2614 pSMB->Fid = fid; /* file handle always le */
2615 pSMB->ByteCount = 0;
2617 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2618 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2620 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2621 } else { /* decode response */
2622 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2623 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2624 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2625 /* BB also check enough total bytes returned */
2626 rc = -EIO; /* bad smb */
2628 if (data_count && (data_count < 2048)) {
2629 char *end_of_smb = 2 /* sizeof byte count */ +
2631 (char *)&pSMBr->ByteCount;
2633 struct reparse_data *reparse_buf =
2634 (struct reparse_data *)
2635 ((char *)&pSMBr->hdr.Protocol
2637 if ((char *)reparse_buf >= end_of_smb) {
2641 if ((reparse_buf->LinkNamesBuf +
2642 reparse_buf->TargetNameOffset +
2643 reparse_buf->TargetNameLen) >
2645 cFYI(1, ("reparse buf beyond SMB"));
2650 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2651 name_len = UniStrnlen((wchar_t *)
2652 (reparse_buf->LinkNamesBuf +
2653 reparse_buf->TargetNameOffset),
2655 reparse_buf->TargetNameLen / 2));
2656 cifs_strfromUCS_le(symlinkinfo,
2657 (__le16 *) (reparse_buf->LinkNamesBuf +
2658 reparse_buf->TargetNameOffset),
2659 name_len, nls_codepage);
2660 } else { /* ASCII names */
2661 strncpy(symlinkinfo,
2662 reparse_buf->LinkNamesBuf +
2663 reparse_buf->TargetNameOffset,
2664 min_t(const int, buflen,
2665 reparse_buf->TargetNameLen));
2669 cFYI(1, ("Invalid return data count on "
2670 "get reparse info ioctl"));
2672 symlinkinfo[buflen] = 0; /* just in case so the caller
2673 does not go off the end of the buffer */
2674 cFYI(1, ("readlink result - %s", symlinkinfo));
2678 cifs_buf_release(pSMB);
2680 /* Note: On -EAGAIN error only caller can retry on handle based calls
2681 since file handle passed in no longer valid */
2686 #ifdef CONFIG_CIFS_POSIX
2688 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2689 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2690 struct cifs_posix_ace *cifs_ace)
2692 /* u8 cifs fields do not need le conversion */
2693 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2694 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2695 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2696 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2701 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2702 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2703 const int acl_type, const int size_of_data_area)
2708 struct cifs_posix_ace *pACE;
2709 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2710 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2712 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2715 if (acl_type & ACL_TYPE_ACCESS) {
2716 count = le16_to_cpu(cifs_acl->access_entry_count);
2717 pACE = &cifs_acl->ace_array[0];
2718 size = sizeof(struct cifs_posix_acl);
2719 size += sizeof(struct cifs_posix_ace) * count;
2720 /* check if we would go beyond end of SMB */
2721 if (size_of_data_area < size) {
2722 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2723 size_of_data_area, size));
2726 } else if (acl_type & ACL_TYPE_DEFAULT) {
2727 count = le16_to_cpu(cifs_acl->access_entry_count);
2728 size = sizeof(struct cifs_posix_acl);
2729 size += sizeof(struct cifs_posix_ace) * count;
2730 /* skip past access ACEs to get to default ACEs */
2731 pACE = &cifs_acl->ace_array[count];
2732 count = le16_to_cpu(cifs_acl->default_entry_count);
2733 size += sizeof(struct cifs_posix_ace) * count;
2734 /* check if we would go beyond end of SMB */
2735 if (size_of_data_area < size)
2742 size = posix_acl_xattr_size(count);
2743 if ((buflen == 0) || (local_acl == NULL)) {
2744 /* used to query ACL EA size */
2745 } else if (size > buflen) {
2747 } else /* buffer big enough */ {
2748 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2749 for (i = 0; i < count ; i++) {
2750 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2757 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2758 const posix_acl_xattr_entry *local_ace)
2760 __u16 rc = 0; /* 0 = ACL converted ok */
2762 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2763 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2764 /* BB is there a better way to handle the large uid? */
2765 if (local_ace->e_id == cpu_to_le32(-1)) {
2766 /* Probably no need to le convert -1 on any arch but can not hurt */
2767 cifs_ace->cifs_uid = cpu_to_le64(-1);
2769 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2770 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2774 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2775 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2776 const int buflen, const int acl_type)
2779 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2780 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2784 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2787 count = posix_acl_xattr_count((size_t)buflen);
2788 cFYI(1, ("setting acl with %d entries from buf of length %d and "
2790 count, buflen, le32_to_cpu(local_acl->a_version)));
2791 if (le32_to_cpu(local_acl->a_version) != 2) {
2792 cFYI(1, ("unknown POSIX ACL version %d",
2793 le32_to_cpu(local_acl->a_version)));
2796 cifs_acl->version = cpu_to_le16(1);
2797 if (acl_type == ACL_TYPE_ACCESS)
2798 cifs_acl->access_entry_count = cpu_to_le16(count);
2799 else if (acl_type == ACL_TYPE_DEFAULT)
2800 cifs_acl->default_entry_count = cpu_to_le16(count);
2802 cFYI(1, ("unknown ACL type %d", acl_type));
2805 for (i = 0; i < count; i++) {
2806 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2807 &local_acl->a_entries[i]);
2809 /* ACE not converted */
2814 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2815 rc += sizeof(struct cifs_posix_acl);
2816 /* BB add check to make sure ACL does not overflow SMB */
2822 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2823 const unsigned char *searchName,
2824 char *acl_inf, const int buflen, const int acl_type,
2825 const struct nls_table *nls_codepage, int remap)
2827 /* SMB_QUERY_POSIX_ACL */
2828 TRANSACTION2_QPI_REQ *pSMB = NULL;
2829 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2833 __u16 params, byte_count;
2835 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2838 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2843 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2845 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2846 PATH_MAX, nls_codepage, remap);
2847 name_len++; /* trailing null */
2849 pSMB->FileName[name_len] = 0;
2850 pSMB->FileName[name_len+1] = 0;
2851 } else { /* BB improve the check for buffer overruns BB */
2852 name_len = strnlen(searchName, PATH_MAX);
2853 name_len++; /* trailing null */
2854 strncpy(pSMB->FileName, searchName, name_len);
2857 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2858 pSMB->TotalDataCount = 0;
2859 pSMB->MaxParameterCount = cpu_to_le16(2);
2860 /* BB find exact max data count below from sess structure BB */
2861 pSMB->MaxDataCount = cpu_to_le16(4000);
2862 pSMB->MaxSetupCount = 0;
2866 pSMB->Reserved2 = 0;
2867 pSMB->ParameterOffset = cpu_to_le16(
2868 offsetof(struct smb_com_transaction2_qpi_req,
2869 InformationLevel) - 4);
2870 pSMB->DataCount = 0;
2871 pSMB->DataOffset = 0;
2872 pSMB->SetupCount = 1;
2873 pSMB->Reserved3 = 0;
2874 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2875 byte_count = params + 1 /* pad */ ;
2876 pSMB->TotalParameterCount = cpu_to_le16(params);
2877 pSMB->ParameterCount = pSMB->TotalParameterCount;
2878 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2879 pSMB->Reserved4 = 0;
2880 pSMB->hdr.smb_buf_length += byte_count;
2881 pSMB->ByteCount = cpu_to_le16(byte_count);
2883 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2884 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2885 cifs_stats_inc(&tcon->num_acl_get);
2887 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2889 /* decode response */
2891 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2892 if (rc || (pSMBr->ByteCount < 2))
2893 /* BB also check enough total bytes returned */
2894 rc = -EIO; /* bad smb */
2896 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2897 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2898 rc = cifs_copy_posix_acl(acl_inf,
2899 (char *)&pSMBr->hdr.Protocol+data_offset,
2900 buflen, acl_type, count);
2903 cifs_buf_release(pSMB);
2910 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2911 const unsigned char *fileName,
2912 const char *local_acl, const int buflen,
2914 const struct nls_table *nls_codepage, int remap)
2916 struct smb_com_transaction2_spi_req *pSMB = NULL;
2917 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2921 int bytes_returned = 0;
2922 __u16 params, byte_count, data_count, param_offset, offset;
2924 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2926 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2930 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2932 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2933 PATH_MAX, nls_codepage, remap);
2934 name_len++; /* trailing null */
2936 } else { /* BB improve the check for buffer overruns BB */
2937 name_len = strnlen(fileName, PATH_MAX);
2938 name_len++; /* trailing null */
2939 strncpy(pSMB->FileName, fileName, name_len);
2941 params = 6 + name_len;
2942 pSMB->MaxParameterCount = cpu_to_le16(2);
2943 /* BB find max SMB size from sess */
2944 pSMB->MaxDataCount = cpu_to_le16(1000);
2945 pSMB->MaxSetupCount = 0;
2949 pSMB->Reserved2 = 0;
2950 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2951 InformationLevel) - 4;
2952 offset = param_offset + params;
2953 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2954 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2956 /* convert to on the wire format for POSIX ACL */
2957 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2959 if (data_count == 0) {
2961 goto setACLerrorExit;
2963 pSMB->DataOffset = cpu_to_le16(offset);
2964 pSMB->SetupCount = 1;
2965 pSMB->Reserved3 = 0;
2966 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2967 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2968 byte_count = 3 /* pad */ + params + data_count;
2969 pSMB->DataCount = cpu_to_le16(data_count);
2970 pSMB->TotalDataCount = pSMB->DataCount;
2971 pSMB->ParameterCount = cpu_to_le16(params);
2972 pSMB->TotalParameterCount = pSMB->ParameterCount;
2973 pSMB->Reserved4 = 0;
2974 pSMB->hdr.smb_buf_length += byte_count;
2975 pSMB->ByteCount = cpu_to_le16(byte_count);
2976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2979 cFYI(1, ("Set POSIX ACL returned %d", rc));
2982 cifs_buf_release(pSMB);
2988 /* BB fix tabs in this function FIXME BB */
2990 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2991 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2994 struct smb_t2_qfi_req *pSMB = NULL;
2995 struct smb_t2_qfi_rsp *pSMBr = NULL;
2997 __u16 params, byte_count;
2999 cFYI(1, ("In GetExtAttr"));
3004 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3009 params = 2 /* level */ + 2 /* fid */;
3010 pSMB->t2.TotalDataCount = 0;
3011 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3012 /* BB find exact max data count below from sess structure BB */
3013 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3014 pSMB->t2.MaxSetupCount = 0;
3015 pSMB->t2.Reserved = 0;
3017 pSMB->t2.Timeout = 0;
3018 pSMB->t2.Reserved2 = 0;
3019 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3021 pSMB->t2.DataCount = 0;
3022 pSMB->t2.DataOffset = 0;
3023 pSMB->t2.SetupCount = 1;
3024 pSMB->t2.Reserved3 = 0;
3025 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3026 byte_count = params + 1 /* pad */ ;
3027 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3028 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3029 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3032 pSMB->hdr.smb_buf_length += byte_count;
3033 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3035 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3036 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3038 cFYI(1, ("error %d in GetExtAttr", rc));
3040 /* decode response */
3041 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3042 if (rc || (pSMBr->ByteCount < 2))
3043 /* BB also check enough total bytes returned */
3044 /* If rc should we check for EOPNOSUPP and
3045 disable the srvino flag? or in caller? */
3046 rc = -EIO; /* bad smb */
3048 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3049 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3050 struct file_chattr_info *pfinfo;
3051 /* BB Do we need a cast or hash here ? */
3053 cFYI(1, ("Illegal size ret in GetExtAttr"));
3057 pfinfo = (struct file_chattr_info *)
3058 (data_offset + (char *) &pSMBr->hdr.Protocol);
3059 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3060 *pMask = le64_to_cpu(pfinfo->mask);
3064 cifs_buf_release(pSMB);
3066 goto GetExtAttrRetry;
3070 #endif /* CONFIG_POSIX */
3072 #ifdef CONFIG_CIFS_EXPERIMENTAL
3073 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3075 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3076 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3080 QUERY_SEC_DESC_REQ *pSMB;
3083 cFYI(1, ("GetCifsACL"));
3088 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3089 8 /* parm len */, tcon, (void **) &pSMB);
3093 pSMB->MaxParameterCount = cpu_to_le32(4);
3094 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3095 pSMB->MaxSetupCount = 0;
3096 pSMB->Fid = fid; /* file handle always le */
3097 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3099 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3100 pSMB->hdr.smb_buf_length += 11;
3101 iov[0].iov_base = (char *)pSMB;
3102 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3104 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3106 cifs_stats_inc(&tcon->num_acl_get);
3108 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3109 } else { /* decode response */
3113 struct smb_com_ntransact_rsp *pSMBr;
3116 /* validate_nttransact */
3117 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3118 &pdata, &parm_len, pbuflen);
3121 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3123 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3125 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3126 rc = -EIO; /* bad smb */
3131 /* BB check that data area is minimum length and as big as acl_len */
3133 acl_len = le32_to_cpu(*parm);
3134 if (acl_len != *pbuflen) {
3135 cERROR(1, ("acl length %d does not match %d",
3136 acl_len, *pbuflen));
3137 if (*pbuflen > acl_len)
3141 /* check if buffer is big enough for the acl
3142 header followed by the smallest SID */
3143 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3144 (*pbuflen >= 64 * 1024)) {
3145 cERROR(1, ("bad acl length %d", *pbuflen));
3149 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3150 if (*acl_inf == NULL) {
3154 memcpy(*acl_inf, pdata, *pbuflen);
3158 if (buf_type == CIFS_SMALL_BUFFER)
3159 cifs_small_buf_release(iov[0].iov_base);
3160 else if (buf_type == CIFS_LARGE_BUFFER)
3161 cifs_buf_release(iov[0].iov_base);
3162 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3167 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3168 struct cifs_ntsd *pntsd, __u32 acllen)
3170 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3172 int bytes_returned = 0;
3173 SET_SEC_DESC_REQ *pSMB = NULL;
3174 NTRANSACT_RSP *pSMBr = NULL;
3177 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3182 pSMB->MaxSetupCount = 0;
3186 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3187 data_count = acllen;
3188 data_offset = param_offset + param_count;
3189 byte_count = 3 /* pad */ + param_count;
3191 pSMB->DataCount = cpu_to_le32(data_count);
3192 pSMB->TotalDataCount = pSMB->DataCount;
3193 pSMB->MaxParameterCount = cpu_to_le32(4);
3194 pSMB->MaxDataCount = cpu_to_le32(16384);
3195 pSMB->ParameterCount = cpu_to_le32(param_count);
3196 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3197 pSMB->TotalParameterCount = pSMB->ParameterCount;
3198 pSMB->DataOffset = cpu_to_le32(data_offset);
3199 pSMB->SetupCount = 0;
3200 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3201 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3203 pSMB->Fid = fid; /* file handle always le */
3204 pSMB->Reserved2 = 0;
3205 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3207 if (pntsd && acllen) {
3208 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3211 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3214 pSMB->hdr.smb_buf_length += byte_count;
3216 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3217 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3219 cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3221 cFYI(1, ("Set CIFS ACL returned %d", rc));
3222 cifs_buf_release(pSMB);
3225 goto setCifsAclRetry;
3230 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3232 /* Legacy Query Path Information call for lookup to old servers such
3234 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3235 const unsigned char *searchName,
3236 FILE_ALL_INFO *pFinfo,
3237 const struct nls_table *nls_codepage, int remap)
3239 QUERY_INFORMATION_REQ *pSMB;
3240 QUERY_INFORMATION_RSP *pSMBr;
3245 cFYI(1, ("In SMBQPath path %s", searchName));
3247 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3252 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3254 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3255 PATH_MAX, nls_codepage, remap);
3256 name_len++; /* trailing null */
3259 name_len = strnlen(searchName, PATH_MAX);
3260 name_len++; /* trailing null */
3261 strncpy(pSMB->FileName, searchName, name_len);
3263 pSMB->BufferFormat = 0x04;
3264 name_len++; /* account for buffer type byte */
3265 pSMB->hdr.smb_buf_length += (__u16) name_len;
3266 pSMB->ByteCount = cpu_to_le16(name_len);
3268 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3269 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3271 cFYI(1, ("Send error in QueryInfo = %d", rc));
3272 } else if (pFinfo) {
3274 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3276 /* decode response */
3277 /* BB FIXME - add time zone adjustment BB */
3278 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3281 /* decode time fields */
3282 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3283 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3284 pFinfo->LastAccessTime = 0;
3285 pFinfo->AllocationSize =
3286 cpu_to_le64(le32_to_cpu(pSMBr->size));
3287 pFinfo->EndOfFile = pFinfo->AllocationSize;
3288 pFinfo->Attributes =
3289 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3291 rc = -EIO; /* bad buffer passed in */
3293 cifs_buf_release(pSMB);
3305 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3306 const unsigned char *searchName,
3307 FILE_ALL_INFO *pFindData,
3308 int legacy /* old style infolevel */,
3309 const struct nls_table *nls_codepage, int remap)
3311 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3312 TRANSACTION2_QPI_REQ *pSMB = NULL;
3313 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3317 __u16 params, byte_count;
3319 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3321 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3326 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3328 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3329 PATH_MAX, nls_codepage, remap);
3330 name_len++; /* trailing null */
3332 } else { /* BB improve the check for buffer overruns BB */
3333 name_len = strnlen(searchName, PATH_MAX);
3334 name_len++; /* trailing null */
3335 strncpy(pSMB->FileName, searchName, name_len);
3338 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3339 pSMB->TotalDataCount = 0;
3340 pSMB->MaxParameterCount = cpu_to_le16(2);
3341 /* BB find exact max SMB PDU from sess structure BB */
3342 pSMB->MaxDataCount = cpu_to_le16(4000);
3343 pSMB->MaxSetupCount = 0;
3347 pSMB->Reserved2 = 0;
3348 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3349 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3350 pSMB->DataCount = 0;
3351 pSMB->DataOffset = 0;
3352 pSMB->SetupCount = 1;
3353 pSMB->Reserved3 = 0;
3354 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3355 byte_count = params + 1 /* pad */ ;
3356 pSMB->TotalParameterCount = cpu_to_le16(params);
3357 pSMB->ParameterCount = pSMB->TotalParameterCount;
3359 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3361 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3362 pSMB->Reserved4 = 0;
3363 pSMB->hdr.smb_buf_length += byte_count;
3364 pSMB->ByteCount = cpu_to_le16(byte_count);
3366 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3367 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3369 cFYI(1, ("Send error in QPathInfo = %d", rc));
3370 } else { /* decode response */
3371 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3373 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3375 else if (!legacy && (pSMBr->ByteCount < 40))
3376 rc = -EIO; /* bad smb */
3377 else if (legacy && (pSMBr->ByteCount < 24))
3378 rc = -EIO; /* 24 or 26 expected but we do not read
3380 else if (pFindData) {
3382 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3384 /* On legacy responses we do not read the last field,
3385 EAsize, fortunately since it varies by subdialect and
3386 also note it differs on Set vs. Get, ie two bytes or 4
3387 bytes depending but we don't care here */
3389 size = sizeof(FILE_INFO_STANDARD);
3391 size = sizeof(FILE_ALL_INFO);
3392 memcpy((char *) pFindData,
3393 (char *) &pSMBr->hdr.Protocol +
3398 cifs_buf_release(pSMB);
3400 goto QPathInfoRetry;
3406 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3407 const unsigned char *searchName,
3408 FILE_UNIX_BASIC_INFO *pFindData,
3409 const struct nls_table *nls_codepage, int remap)
3411 /* SMB_QUERY_FILE_UNIX_BASIC */
3412 TRANSACTION2_QPI_REQ *pSMB = NULL;
3413 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3415 int bytes_returned = 0;
3417 __u16 params, byte_count;
3419 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3421 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3426 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3428 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3429 PATH_MAX, nls_codepage, remap);
3430 name_len++; /* trailing null */
3432 } else { /* BB improve the check for buffer overruns BB */
3433 name_len = strnlen(searchName, PATH_MAX);
3434 name_len++; /* trailing null */
3435 strncpy(pSMB->FileName, searchName, name_len);
3438 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3439 pSMB->TotalDataCount = 0;
3440 pSMB->MaxParameterCount = cpu_to_le16(2);
3441 /* BB find exact max SMB PDU from sess structure BB */
3442 pSMB->MaxDataCount = cpu_to_le16(4000);
3443 pSMB->MaxSetupCount = 0;
3447 pSMB->Reserved2 = 0;
3448 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3449 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3450 pSMB->DataCount = 0;
3451 pSMB->DataOffset = 0;
3452 pSMB->SetupCount = 1;
3453 pSMB->Reserved3 = 0;
3454 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3455 byte_count = params + 1 /* pad */ ;
3456 pSMB->TotalParameterCount = cpu_to_le16(params);
3457 pSMB->ParameterCount = pSMB->TotalParameterCount;
3458 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3459 pSMB->Reserved4 = 0;
3460 pSMB->hdr.smb_buf_length += byte_count;
3461 pSMB->ByteCount = cpu_to_le16(byte_count);
3463 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3464 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3466 cFYI(1, ("Send error in QPathInfo = %d", rc));
3467 } else { /* decode response */
3468 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3470 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3471 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3472 "Unix Extensions can be disabled on mount "
3473 "by specifying the nosfu mount option."));
3474 rc = -EIO; /* bad smb */
3476 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3477 memcpy((char *) pFindData,
3478 (char *) &pSMBr->hdr.Protocol +
3480 sizeof(FILE_UNIX_BASIC_INFO));
3483 cifs_buf_release(pSMB);
3485 goto UnixQPathInfoRetry;
3490 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3492 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3493 const char *searchName,
3494 const struct nls_table *nls_codepage,
3496 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3498 /* level 257 SMB_ */
3499 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3500 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3501 T2_FFIRST_RSP_PARMS *parms;
3503 int bytes_returned = 0;
3505 __u16 params, byte_count;
3507 cFYI(1, ("In FindFirst for %s", searchName));
3510 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3515 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3517 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3518 PATH_MAX, nls_codepage, remap);
3519 /* We can not add the asterik earlier in case
3520 it got remapped to 0xF03A as if it were part of the
3521 directory name instead of a wildcard */
3523 pSMB->FileName[name_len] = dirsep;
3524 pSMB->FileName[name_len+1] = 0;
3525 pSMB->FileName[name_len+2] = '*';
3526 pSMB->FileName[name_len+3] = 0;
3527 name_len += 4; /* now the trailing null */
3528 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3529 pSMB->FileName[name_len+1] = 0;
3531 } else { /* BB add check for overrun of SMB buf BB */
3532 name_len = strnlen(searchName, PATH_MAX);
3533 /* BB fix here and in unicode clause above ie
3534 if (name_len > buffersize-header)
3535 free buffer exit; BB */
3536 strncpy(pSMB->FileName, searchName, name_len);
3537 pSMB->FileName[name_len] = dirsep;
3538 pSMB->FileName[name_len+1] = '*';
3539 pSMB->FileName[name_len+2] = 0;
3543 params = 12 + name_len /* includes null */ ;
3544 pSMB->TotalDataCount = 0; /* no EAs */
3545 pSMB->MaxParameterCount = cpu_to_le16(10);
3546 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3547 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3548 pSMB->MaxSetupCount = 0;
3552 pSMB->Reserved2 = 0;
3553 byte_count = params + 1 /* pad */ ;
3554 pSMB->TotalParameterCount = cpu_to_le16(params);
3555 pSMB->ParameterCount = pSMB->TotalParameterCount;
3556 pSMB->ParameterOffset = cpu_to_le16(
3557 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3559 pSMB->DataCount = 0;
3560 pSMB->DataOffset = 0;
3561 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3562 pSMB->Reserved3 = 0;
3563 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3564 pSMB->SearchAttributes =
3565 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3567 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3568 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3569 CIFS_SEARCH_RETURN_RESUME);
3570 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3572 /* BB what should we set StorageType to? Does it matter? BB */
3573 pSMB->SearchStorageType = 0;
3574 pSMB->hdr.smb_buf_length += byte_count;
3575 pSMB->ByteCount = cpu_to_le16(byte_count);
3577 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3578 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3579 cifs_stats_inc(&tcon->num_ffirst);
3581 if (rc) {/* BB add logic to retry regular search if Unix search
3582 rejected unexpectedly by server */
3583 /* BB Add code to handle unsupported level rc */
3584 cFYI(1, ("Error in FindFirst = %d", rc));
3586 cifs_buf_release(pSMB);
3588 /* BB eventually could optimize out free and realloc of buf */
3591 goto findFirstRetry;
3592 } else { /* decode response */
3593 /* BB remember to free buffer if error BB */
3594 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3598 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3599 psrch_inf->unicode = true;
3601 psrch_inf->unicode = false;
3603 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3604 psrch_inf->smallBuf = 0;
3605 psrch_inf->srch_entries_start =
3606 (char *) &pSMBr->hdr.Protocol +
3607 le16_to_cpu(pSMBr->t2.DataOffset);
3608 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3609 le16_to_cpu(pSMBr->t2.ParameterOffset));
3611 if (parms->EndofSearch)
3612 psrch_inf->endOfSearch = true;
3614 psrch_inf->endOfSearch = false;
3616 psrch_inf->entries_in_buffer =
3617 le16_to_cpu(parms->SearchCount);
3618 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3619 psrch_inf->entries_in_buffer;
3620 lnoff = le16_to_cpu(parms->LastNameOffset);
3621 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3623 cERROR(1, ("ignoring corrupt resume name"));
3624 psrch_inf->last_entry = NULL;
3628 psrch_inf->last_entry = psrch_inf->srch_entries_start +
3631 *pnetfid = parms->SearchHandle;
3633 cifs_buf_release(pSMB);
3640 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3641 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3643 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3644 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3645 T2_FNEXT_RSP_PARMS *parms;
3646 char *response_data;
3648 int bytes_returned, name_len;
3649 __u16 params, byte_count;
3651 cFYI(1, ("In FindNext"));
3653 if (psrch_inf->endOfSearch)
3656 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3661 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3663 pSMB->TotalDataCount = 0; /* no EAs */
3664 pSMB->MaxParameterCount = cpu_to_le16(8);
3665 pSMB->MaxDataCount =
3666 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3668 pSMB->MaxSetupCount = 0;
3672 pSMB->Reserved2 = 0;
3673 pSMB->ParameterOffset = cpu_to_le16(
3674 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3675 pSMB->DataCount = 0;
3676 pSMB->DataOffset = 0;
3677 pSMB->SetupCount = 1;
3678 pSMB->Reserved3 = 0;
3679 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3680 pSMB->SearchHandle = searchHandle; /* always kept as le */
3682 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3683 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3684 pSMB->ResumeKey = psrch_inf->resume_key;
3686 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3688 name_len = psrch_inf->resume_name_len;
3690 if (name_len < PATH_MAX) {
3691 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3692 byte_count += name_len;
3693 /* 14 byte parm len above enough for 2 byte null terminator */
3694 pSMB->ResumeFileName[name_len] = 0;
3695 pSMB->ResumeFileName[name_len+1] = 0;
3698 goto FNext2_err_exit;
3700 byte_count = params + 1 /* pad */ ;
3701 pSMB->TotalParameterCount = cpu_to_le16(params);
3702 pSMB->ParameterCount = pSMB->TotalParameterCount;
3703 pSMB->hdr.smb_buf_length += byte_count;
3704 pSMB->ByteCount = cpu_to_le16(byte_count);
3706 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3707 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3708 cifs_stats_inc(&tcon->num_fnext);
3711 psrch_inf->endOfSearch = true;
3712 cifs_buf_release(pSMB);
3713 rc = 0; /* search probably was closed at end of search*/
3715 cFYI(1, ("FindNext returned = %d", rc));
3716 } else { /* decode response */
3717 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3722 /* BB fixme add lock for file (srch_info) struct here */
3723 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3724 psrch_inf->unicode = true;
3726 psrch_inf->unicode = false;
3727 response_data = (char *) &pSMBr->hdr.Protocol +
3728 le16_to_cpu(pSMBr->t2.ParameterOffset);
3729 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3730 response_data = (char *)&pSMBr->hdr.Protocol +
3731 le16_to_cpu(pSMBr->t2.DataOffset);
3732 if (psrch_inf->smallBuf)
3733 cifs_small_buf_release(
3734 psrch_inf->ntwrk_buf_start);
3736 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3737 psrch_inf->srch_entries_start = response_data;
3738 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3739 psrch_inf->smallBuf = 0;
3740 if (parms->EndofSearch)
3741 psrch_inf->endOfSearch = true;
3743 psrch_inf->endOfSearch = false;
3744 psrch_inf->entries_in_buffer =
3745 le16_to_cpu(parms->SearchCount);
3746 psrch_inf->index_of_last_entry +=
3747 psrch_inf->entries_in_buffer;
3748 lnoff = le16_to_cpu(parms->LastNameOffset);
3749 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3751 cERROR(1, ("ignoring corrupt resume name"));
3752 psrch_inf->last_entry = NULL;
3755 psrch_inf->last_entry =
3756 psrch_inf->srch_entries_start + lnoff;
3758 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3759 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3761 /* BB fixme add unlock here */
3766 /* BB On error, should we leave previous search buf (and count and
3767 last entry fields) intact or free the previous one? */
3769 /* Note: On -EAGAIN error only caller can retry on handle based calls
3770 since file handle passed in no longer valid */
3773 cifs_buf_release(pSMB);
3778 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3779 const __u16 searchHandle)
3782 FINDCLOSE_REQ *pSMB = NULL;
3784 cFYI(1, ("In CIFSSMBFindClose"));
3785 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3787 /* no sense returning error if session restarted
3788 as file handle has been closed */
3794 pSMB->FileID = searchHandle;
3795 pSMB->ByteCount = 0;
3796 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3798 cERROR(1, ("Send error in FindClose = %d", rc));
3800 cifs_stats_inc(&tcon->num_fclose);
3802 /* Since session is dead, search handle closed on server already */
3810 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3811 const unsigned char *searchName,
3812 __u64 *inode_number,
3813 const struct nls_table *nls_codepage, int remap)
3816 TRANSACTION2_QPI_REQ *pSMB = NULL;
3817 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3818 int name_len, bytes_returned;
3819 __u16 params, byte_count;
3821 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3825 GetInodeNumberRetry:
3826 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3831 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3833 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3834 PATH_MAX, nls_codepage, remap);
3835 name_len++; /* trailing null */
3837 } else { /* BB improve the check for buffer overruns BB */
3838 name_len = strnlen(searchName, PATH_MAX);
3839 name_len++; /* trailing null */
3840 strncpy(pSMB->FileName, searchName, name_len);
3843 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3844 pSMB->TotalDataCount = 0;
3845 pSMB->MaxParameterCount = cpu_to_le16(2);
3846 /* BB find exact max data count below from sess structure BB */
3847 pSMB->MaxDataCount = cpu_to_le16(4000);
3848 pSMB->MaxSetupCount = 0;
3852 pSMB->Reserved2 = 0;
3853 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3854 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3855 pSMB->DataCount = 0;
3856 pSMB->DataOffset = 0;
3857 pSMB->SetupCount = 1;
3858 pSMB->Reserved3 = 0;
3859 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3860 byte_count = params + 1 /* pad */ ;
3861 pSMB->TotalParameterCount = cpu_to_le16(params);
3862 pSMB->ParameterCount = pSMB->TotalParameterCount;
3863 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3864 pSMB->Reserved4 = 0;
3865 pSMB->hdr.smb_buf_length += byte_count;
3866 pSMB->ByteCount = cpu_to_le16(byte_count);
3868 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3871 cFYI(1, ("error %d in QueryInternalInfo", rc));
3873 /* decode response */
3874 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3875 if (rc || (pSMBr->ByteCount < 2))
3876 /* BB also check enough total bytes returned */
3877 /* If rc should we check for EOPNOSUPP and
3878 disable the srvino flag? or in caller? */
3879 rc = -EIO; /* bad smb */
3881 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3882 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3883 struct file_internal_info *pfinfo;
3884 /* BB Do we need a cast or hash here ? */
3886 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3888 goto GetInodeNumOut;
3890 pfinfo = (struct file_internal_info *)
3891 (data_offset + (char *) &pSMBr->hdr.Protocol);
3892 *inode_number = pfinfo->UniqueId;
3896 cifs_buf_release(pSMB);
3898 goto GetInodeNumberRetry;
3902 /* computes length of UCS string converted to host codepage
3904 * @maxlen: length of the input string in UCS characters
3907 * return: size of input string in host codepage
3909 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3910 const struct nls_table *nls_codepage) {
3915 for (i = 0; (i < maxlen) && src[i]; ++i) {
3916 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3917 to, NLS_MAX_CHARSET_SIZE);
3918 hostlen += charlen > 0 ? charlen : 1;
3923 /* parses DFS refferal V3 structure
3924 * caller is responsible for freeing target_nodes
3927 * on failure - errno
3930 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3931 unsigned int *num_of_nodes,
3932 struct dfs_info3_param **target_nodes,
3933 const struct nls_table *nls_codepage, int remap,
3934 const char *searchName)
3939 struct dfs_referral_level_3 *ref;
3941 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3945 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3947 if (*num_of_nodes < 1) {
3948 cERROR(1, ("num_referrals: must be at least > 0,"
3949 "but we get num_referrals = %d\n", *num_of_nodes));
3951 goto parse_DFS_referrals_exit;
3954 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3955 if (ref->VersionNumber != cpu_to_le16(3)) {
3956 cERROR(1, ("Referrals of V%d version are not supported,"
3957 "should be V3", le16_to_cpu(ref->VersionNumber)));
3959 goto parse_DFS_referrals_exit;
3962 /* get the upper boundary of the resp buffer */
3963 data_end = (char *)(&(pSMBr->PathConsumed)) +
3964 le16_to_cpu(pSMBr->t2.DataCount);
3966 cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3968 le16_to_cpu(pSMBr->DFSFlags)));
3970 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3971 *num_of_nodes, GFP_KERNEL);
3972 if (*target_nodes == NULL) {
3973 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3975 goto parse_DFS_referrals_exit;
3978 /* collect neccessary data from referrals */
3979 for (i = 0; i < *num_of_nodes; i++) {
3982 struct dfs_info3_param *node = (*target_nodes)+i;
3984 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3986 __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL);
3987 cifsConvertToUCS((__le16 *) tmp, searchName,
3988 PATH_MAX, nls_codepage, remap);
3989 node->path_consumed = hostlen_fromUCS(tmp,
3990 le16_to_cpu(pSMBr->PathConsumed)/2,
3994 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3996 node->server_type = le16_to_cpu(ref->ServerType);
3997 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4000 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4001 max_len = data_end - temp;
4002 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4003 max_len, is_unicode, nls_codepage);
4005 goto parse_DFS_referrals_exit;
4007 /* copy link target UNC */
4008 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4009 max_len = data_end - temp;
4010 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4011 max_len, is_unicode, nls_codepage);
4013 goto parse_DFS_referrals_exit;
4015 ref += le16_to_cpu(ref->Size);
4018 parse_DFS_referrals_exit:
4020 free_dfs_info_array(*target_nodes, *num_of_nodes);
4021 *target_nodes = NULL;
4028 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4029 const unsigned char *searchName,
4030 struct dfs_info3_param **target_nodes,
4031 unsigned int *num_of_nodes,
4032 const struct nls_table *nls_codepage, int remap)
4034 /* TRANS2_GET_DFS_REFERRAL */
4035 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4036 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4040 __u16 params, byte_count;
4042 *target_nodes = NULL;
4044 cFYI(1, ("In GetDFSRefer the path %s", searchName));
4048 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4053 /* server pointer checked in called function,
4054 but should never be null here anyway */
4055 pSMB->hdr.Mid = GetNextMid(ses->server);
4056 pSMB->hdr.Tid = ses->ipc_tid;
4057 pSMB->hdr.Uid = ses->Suid;
4058 if (ses->capabilities & CAP_STATUS32)
4059 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4060 if (ses->capabilities & CAP_DFS)
4061 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4063 if (ses->capabilities & CAP_UNICODE) {
4064 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4066 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4067 searchName, PATH_MAX, nls_codepage, remap);
4068 name_len++; /* trailing null */
4070 } else { /* BB improve the check for buffer overruns BB */
4071 name_len = strnlen(searchName, PATH_MAX);
4072 name_len++; /* trailing null */
4073 strncpy(pSMB->RequestFileName, searchName, name_len);
4077 if (ses->server->secMode &
4078 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4079 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4082 pSMB->hdr.Uid = ses->Suid;
4084 params = 2 /* level */ + name_len /*includes null */ ;
4085 pSMB->TotalDataCount = 0;
4086 pSMB->DataCount = 0;
4087 pSMB->DataOffset = 0;
4088 pSMB->MaxParameterCount = 0;
4089 /* BB find exact max SMB PDU from sess structure BB */
4090 pSMB->MaxDataCount = cpu_to_le16(4000);
4091 pSMB->MaxSetupCount = 0;
4095 pSMB->Reserved2 = 0;
4096 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4097 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4098 pSMB->SetupCount = 1;
4099 pSMB->Reserved3 = 0;
4100 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4101 byte_count = params + 3 /* pad */ ;
4102 pSMB->ParameterCount = cpu_to_le16(params);
4103 pSMB->TotalParameterCount = pSMB->ParameterCount;
4104 pSMB->MaxReferralLevel = cpu_to_le16(3);
4105 pSMB->hdr.smb_buf_length += byte_count;
4106 pSMB->ByteCount = cpu_to_le16(byte_count);
4108 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4109 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4111 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4114 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4116 /* BB Also check if enough total bytes returned? */
4117 if (rc || (pSMBr->ByteCount < 17)) {
4118 rc = -EIO; /* bad smb */
4122 cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
4124 le16_to_cpu(pSMBr->t2.DataOffset)));
4126 /* parse returned result into more usable form */
4127 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4128 target_nodes, nls_codepage, remap,
4132 cifs_buf_release(pSMB);
4140 /* Query File System Info such as free space to old servers such as Win 9x */
4142 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4144 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4145 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4146 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4147 FILE_SYSTEM_ALLOC_INFO *response_data;
4149 int bytes_returned = 0;
4150 __u16 params, byte_count;
4152 cFYI(1, ("OldQFSInfo"));
4154 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4159 params = 2; /* level */
4160 pSMB->TotalDataCount = 0;
4161 pSMB->MaxParameterCount = cpu_to_le16(2);
4162 pSMB->MaxDataCount = cpu_to_le16(1000);
4163 pSMB->MaxSetupCount = 0;
4167 pSMB->Reserved2 = 0;
4168 byte_count = params + 1 /* pad */ ;
4169 pSMB->TotalParameterCount = cpu_to_le16(params);
4170 pSMB->ParameterCount = pSMB->TotalParameterCount;
4171 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4172 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4173 pSMB->DataCount = 0;
4174 pSMB->DataOffset = 0;
4175 pSMB->SetupCount = 1;
4176 pSMB->Reserved3 = 0;
4177 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4178 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4179 pSMB->hdr.smb_buf_length += byte_count;
4180 pSMB->ByteCount = cpu_to_le16(byte_count);
4182 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4183 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4185 cFYI(1, ("Send error in QFSInfo = %d", rc));
4186 } else { /* decode response */
4187 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4189 if (rc || (pSMBr->ByteCount < 18))
4190 rc = -EIO; /* bad smb */
4192 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4193 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4194 pSMBr->ByteCount, data_offset));
4196 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4197 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4199 le16_to_cpu(response_data->BytesPerSector) *
4200 le32_to_cpu(response_data->
4201 SectorsPerAllocationUnit);
4203 le32_to_cpu(response_data->TotalAllocationUnits);
4204 FSData->f_bfree = FSData->f_bavail =
4205 le32_to_cpu(response_data->FreeAllocationUnits);
4207 ("Blocks: %lld Free: %lld Block size %ld",
4208 (unsigned long long)FSData->f_blocks,
4209 (unsigned long long)FSData->f_bfree,
4213 cifs_buf_release(pSMB);
4216 goto oldQFSInfoRetry;
4222 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4224 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4225 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4226 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4227 FILE_SYSTEM_INFO *response_data;
4229 int bytes_returned = 0;
4230 __u16 params, byte_count;
4232 cFYI(1, ("In QFSInfo"));
4234 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4239 params = 2; /* level */
4240 pSMB->TotalDataCount = 0;
4241 pSMB->MaxParameterCount = cpu_to_le16(2);
4242 pSMB->MaxDataCount = cpu_to_le16(1000);
4243 pSMB->MaxSetupCount = 0;
4247 pSMB->Reserved2 = 0;
4248 byte_count = params + 1 /* pad */ ;
4249 pSMB->TotalParameterCount = cpu_to_le16(params);
4250 pSMB->ParameterCount = pSMB->TotalParameterCount;
4251 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4252 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4253 pSMB->DataCount = 0;
4254 pSMB->DataOffset = 0;
4255 pSMB->SetupCount = 1;
4256 pSMB->Reserved3 = 0;
4257 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4258 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4259 pSMB->hdr.smb_buf_length += byte_count;
4260 pSMB->ByteCount = cpu_to_le16(byte_count);
4262 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4263 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4265 cFYI(1, ("Send error in QFSInfo = %d", rc));
4266 } else { /* decode response */
4267 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4269 if (rc || (pSMBr->ByteCount < 24))
4270 rc = -EIO; /* bad smb */
4272 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4276 *) (((char *) &pSMBr->hdr.Protocol) +
4279 le32_to_cpu(response_data->BytesPerSector) *
4280 le32_to_cpu(response_data->
4281 SectorsPerAllocationUnit);
4283 le64_to_cpu(response_data->TotalAllocationUnits);
4284 FSData->f_bfree = FSData->f_bavail =
4285 le64_to_cpu(response_data->FreeAllocationUnits);
4287 ("Blocks: %lld Free: %lld Block size %ld",
4288 (unsigned long long)FSData->f_blocks,
4289 (unsigned long long)FSData->f_bfree,
4293 cifs_buf_release(pSMB);
4302 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4304 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4305 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4306 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4307 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4309 int bytes_returned = 0;
4310 __u16 params, byte_count;
4312 cFYI(1, ("In QFSAttributeInfo"));
4314 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4319 params = 2; /* level */
4320 pSMB->TotalDataCount = 0;
4321 pSMB->MaxParameterCount = cpu_to_le16(2);
4322 /* BB find exact max SMB PDU from sess structure BB */
4323 pSMB->MaxDataCount = cpu_to_le16(1000);
4324 pSMB->MaxSetupCount = 0;
4328 pSMB->Reserved2 = 0;
4329 byte_count = params + 1 /* pad */ ;
4330 pSMB->TotalParameterCount = cpu_to_le16(params);
4331 pSMB->ParameterCount = pSMB->TotalParameterCount;
4332 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4333 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4334 pSMB->DataCount = 0;
4335 pSMB->DataOffset = 0;
4336 pSMB->SetupCount = 1;
4337 pSMB->Reserved3 = 0;
4338 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4339 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4340 pSMB->hdr.smb_buf_length += byte_count;
4341 pSMB->ByteCount = cpu_to_le16(byte_count);
4343 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4344 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4346 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4347 } else { /* decode response */
4348 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4350 if (rc || (pSMBr->ByteCount < 13)) {
4351 /* BB also check if enough bytes returned */
4352 rc = -EIO; /* bad smb */
4354 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4356 (FILE_SYSTEM_ATTRIBUTE_INFO
4357 *) (((char *) &pSMBr->hdr.Protocol) +
4359 memcpy(&tcon->fsAttrInfo, response_data,
4360 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4363 cifs_buf_release(pSMB);
4366 goto QFSAttributeRetry;
4372 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4374 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4375 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4376 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4377 FILE_SYSTEM_DEVICE_INFO *response_data;
4379 int bytes_returned = 0;
4380 __u16 params, byte_count;
4382 cFYI(1, ("In QFSDeviceInfo"));
4384 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4389 params = 2; /* level */
4390 pSMB->TotalDataCount = 0;
4391 pSMB->MaxParameterCount = cpu_to_le16(2);
4392 /* BB find exact max SMB PDU from sess structure BB */
4393 pSMB->MaxDataCount = cpu_to_le16(1000);
4394 pSMB->MaxSetupCount = 0;
4398 pSMB->Reserved2 = 0;
4399 byte_count = params + 1 /* pad */ ;
4400 pSMB->TotalParameterCount = cpu_to_le16(params);
4401 pSMB->ParameterCount = pSMB->TotalParameterCount;
4402 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4403 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4405 pSMB->DataCount = 0;
4406 pSMB->DataOffset = 0;
4407 pSMB->SetupCount = 1;
4408 pSMB->Reserved3 = 0;
4409 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4410 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4411 pSMB->hdr.smb_buf_length += byte_count;
4412 pSMB->ByteCount = cpu_to_le16(byte_count);
4414 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4415 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4417 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4418 } else { /* decode response */
4419 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4421 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4422 rc = -EIO; /* bad smb */
4424 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4426 (FILE_SYSTEM_DEVICE_INFO *)
4427 (((char *) &pSMBr->hdr.Protocol) +
4429 memcpy(&tcon->fsDevInfo, response_data,
4430 sizeof(FILE_SYSTEM_DEVICE_INFO));
4433 cifs_buf_release(pSMB);
4436 goto QFSDeviceRetry;
4442 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4444 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4445 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4446 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4447 FILE_SYSTEM_UNIX_INFO *response_data;
4449 int bytes_returned = 0;
4450 __u16 params, byte_count;
4452 cFYI(1, ("In QFSUnixInfo"));
4454 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4459 params = 2; /* level */
4460 pSMB->TotalDataCount = 0;
4461 pSMB->DataCount = 0;
4462 pSMB->DataOffset = 0;
4463 pSMB->MaxParameterCount = cpu_to_le16(2);
4464 /* BB find exact max SMB PDU from sess structure BB */
4465 pSMB->MaxDataCount = cpu_to_le16(100);
4466 pSMB->MaxSetupCount = 0;
4470 pSMB->Reserved2 = 0;
4471 byte_count = params + 1 /* pad */ ;
4472 pSMB->ParameterCount = cpu_to_le16(params);
4473 pSMB->TotalParameterCount = pSMB->ParameterCount;
4474 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4475 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4476 pSMB->SetupCount = 1;
4477 pSMB->Reserved3 = 0;
4478 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4479 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4480 pSMB->hdr.smb_buf_length += byte_count;
4481 pSMB->ByteCount = cpu_to_le16(byte_count);
4483 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4484 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4486 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4487 } else { /* decode response */
4488 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4490 if (rc || (pSMBr->ByteCount < 13)) {
4491 rc = -EIO; /* bad smb */
4493 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4495 (FILE_SYSTEM_UNIX_INFO
4496 *) (((char *) &pSMBr->hdr.Protocol) +
4498 memcpy(&tcon->fsUnixInfo, response_data,
4499 sizeof(FILE_SYSTEM_UNIX_INFO));
4502 cifs_buf_release(pSMB);
4512 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4514 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4515 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4516 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4518 int bytes_returned = 0;
4519 __u16 params, param_offset, offset, byte_count;
4521 cFYI(1, ("In SETFSUnixInfo"));
4523 /* BB switch to small buf init to save memory */
4524 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4529 params = 4; /* 2 bytes zero followed by info level. */
4530 pSMB->MaxSetupCount = 0;
4534 pSMB->Reserved2 = 0;
4535 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4537 offset = param_offset + params;
4539 pSMB->MaxParameterCount = cpu_to_le16(4);
4540 /* BB find exact max SMB PDU from sess structure BB */
4541 pSMB->MaxDataCount = cpu_to_le16(100);
4542 pSMB->SetupCount = 1;
4543 pSMB->Reserved3 = 0;
4544 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4545 byte_count = 1 /* pad */ + params + 12;
4547 pSMB->DataCount = cpu_to_le16(12);
4548 pSMB->ParameterCount = cpu_to_le16(params);
4549 pSMB->TotalDataCount = pSMB->DataCount;
4550 pSMB->TotalParameterCount = pSMB->ParameterCount;
4551 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4552 pSMB->DataOffset = cpu_to_le16(offset);
4556 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4559 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4560 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4561 pSMB->ClientUnixCap = cpu_to_le64(cap);
4563 pSMB->hdr.smb_buf_length += byte_count;
4564 pSMB->ByteCount = cpu_to_le16(byte_count);
4566 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4567 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4569 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4570 } else { /* decode response */
4571 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4573 rc = -EIO; /* bad smb */
4575 cifs_buf_release(pSMB);
4578 goto SETFSUnixRetry;
4586 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4587 struct kstatfs *FSData)
4589 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4590 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4591 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4592 FILE_SYSTEM_POSIX_INFO *response_data;
4594 int bytes_returned = 0;
4595 __u16 params, byte_count;
4597 cFYI(1, ("In QFSPosixInfo"));
4599 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4604 params = 2; /* level */
4605 pSMB->TotalDataCount = 0;
4606 pSMB->DataCount = 0;
4607 pSMB->DataOffset = 0;
4608 pSMB->MaxParameterCount = cpu_to_le16(2);
4609 /* BB find exact max SMB PDU from sess structure BB */
4610 pSMB->MaxDataCount = cpu_to_le16(100);
4611 pSMB->MaxSetupCount = 0;
4615 pSMB->Reserved2 = 0;
4616 byte_count = params + 1 /* pad */ ;
4617 pSMB->ParameterCount = cpu_to_le16(params);
4618 pSMB->TotalParameterCount = pSMB->ParameterCount;
4619 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4620 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4621 pSMB->SetupCount = 1;
4622 pSMB->Reserved3 = 0;
4623 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4624 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4625 pSMB->hdr.smb_buf_length += byte_count;
4626 pSMB->ByteCount = cpu_to_le16(byte_count);
4628 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4629 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4631 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4632 } else { /* decode response */
4633 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4635 if (rc || (pSMBr->ByteCount < 13)) {
4636 rc = -EIO; /* bad smb */
4638 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4640 (FILE_SYSTEM_POSIX_INFO
4641 *) (((char *) &pSMBr->hdr.Protocol) +
4644 le32_to_cpu(response_data->BlockSize);
4646 le64_to_cpu(response_data->TotalBlocks);
4648 le64_to_cpu(response_data->BlocksAvail);
4649 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4650 FSData->f_bavail = FSData->f_bfree;
4653 le64_to_cpu(response_data->UserBlocksAvail);
4655 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4657 le64_to_cpu(response_data->TotalFileNodes);
4658 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4660 le64_to_cpu(response_data->FreeFileNodes);
4663 cifs_buf_release(pSMB);
4672 /* We can not use write of zero bytes trick to
4673 set file size due to need for large file support. Also note that
4674 this SetPathInfo is preferred to SetFileInfo based method in next
4675 routine which is only needed to work around a sharing violation bug
4676 in Samba which this routine can run into */
4679 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4680 __u64 size, bool SetAllocation,
4681 const struct nls_table *nls_codepage, int remap)
4683 struct smb_com_transaction2_spi_req *pSMB = NULL;
4684 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4685 struct file_end_of_file_info *parm_data;
4688 int bytes_returned = 0;
4689 __u16 params, byte_count, data_count, param_offset, offset;
4691 cFYI(1, ("In SetEOF"));
4693 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4698 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4700 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4701 PATH_MAX, nls_codepage, remap);
4702 name_len++; /* trailing null */
4704 } else { /* BB improve the check for buffer overruns BB */
4705 name_len = strnlen(fileName, PATH_MAX);
4706 name_len++; /* trailing null */
4707 strncpy(pSMB->FileName, fileName, name_len);
4709 params = 6 + name_len;
4710 data_count = sizeof(struct file_end_of_file_info);
4711 pSMB->MaxParameterCount = cpu_to_le16(2);
4712 pSMB->MaxDataCount = cpu_to_le16(4100);
4713 pSMB->MaxSetupCount = 0;
4717 pSMB->Reserved2 = 0;
4718 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4719 InformationLevel) - 4;
4720 offset = param_offset + params;
4721 if (SetAllocation) {
4722 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4723 pSMB->InformationLevel =
4724 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4726 pSMB->InformationLevel =
4727 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4728 } else /* Set File Size */ {
4729 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4730 pSMB->InformationLevel =
4731 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4733 pSMB->InformationLevel =
4734 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4738 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4740 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4741 pSMB->DataOffset = cpu_to_le16(offset);
4742 pSMB->SetupCount = 1;
4743 pSMB->Reserved3 = 0;
4744 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4745 byte_count = 3 /* pad */ + params + data_count;
4746 pSMB->DataCount = cpu_to_le16(data_count);
4747 pSMB->TotalDataCount = pSMB->DataCount;
4748 pSMB->ParameterCount = cpu_to_le16(params);
4749 pSMB->TotalParameterCount = pSMB->ParameterCount;
4750 pSMB->Reserved4 = 0;
4751 pSMB->hdr.smb_buf_length += byte_count;
4752 parm_data->FileSize = cpu_to_le64(size);
4753 pSMB->ByteCount = cpu_to_le16(byte_count);
4754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4757 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4759 cifs_buf_release(pSMB);
4768 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4769 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4771 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4773 struct file_end_of_file_info *parm_data;
4775 __u16 params, param_offset, offset, byte_count, count;
4777 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4779 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4784 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4785 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4788 pSMB->MaxSetupCount = 0;
4792 pSMB->Reserved2 = 0;
4793 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4794 offset = param_offset + params;
4796 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4798 count = sizeof(struct file_end_of_file_info);
4799 pSMB->MaxParameterCount = cpu_to_le16(2);
4800 /* BB find exact max SMB PDU from sess structure BB */
4801 pSMB->MaxDataCount = cpu_to_le16(1000);
4802 pSMB->SetupCount = 1;
4803 pSMB->Reserved3 = 0;
4804 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4805 byte_count = 3 /* pad */ + params + count;
4806 pSMB->DataCount = cpu_to_le16(count);
4807 pSMB->ParameterCount = cpu_to_le16(params);
4808 pSMB->TotalDataCount = pSMB->DataCount;
4809 pSMB->TotalParameterCount = pSMB->ParameterCount;
4810 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4812 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4814 pSMB->DataOffset = cpu_to_le16(offset);
4815 parm_data->FileSize = cpu_to_le64(size);
4817 if (SetAllocation) {
4818 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4819 pSMB->InformationLevel =
4820 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4822 pSMB->InformationLevel =
4823 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4824 } else /* Set File Size */ {
4825 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4826 pSMB->InformationLevel =
4827 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4829 pSMB->InformationLevel =
4830 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4832 pSMB->Reserved4 = 0;
4833 pSMB->hdr.smb_buf_length += byte_count;
4834 pSMB->ByteCount = cpu_to_le16(byte_count);
4835 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4838 ("Send error in SetFileInfo (SetFileSize) = %d",
4842 /* Note: On -EAGAIN error only caller can retry on handle based calls
4843 since file handle passed in no longer valid */
4848 /* Some legacy servers such as NT4 require that the file times be set on
4849 an open handle, rather than by pathname - this is awkward due to
4850 potential access conflicts on the open, but it is unavoidable for these
4851 old servers since the only other choice is to go from 100 nanosecond DCE
4852 time and resort to the original setpathinfo level which takes the ancient
4853 DOS time format with 2 second granularity */
4855 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4856 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4858 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4861 __u16 params, param_offset, offset, byte_count, count;
4863 cFYI(1, ("Set Times (via SetFileInfo)"));
4864 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4869 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4870 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4873 pSMB->MaxSetupCount = 0;
4877 pSMB->Reserved2 = 0;
4878 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4879 offset = param_offset + params;
4881 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4883 count = sizeof(FILE_BASIC_INFO);
4884 pSMB->MaxParameterCount = cpu_to_le16(2);
4885 /* BB find max SMB PDU from sess */
4886 pSMB->MaxDataCount = cpu_to_le16(1000);
4887 pSMB->SetupCount = 1;
4888 pSMB->Reserved3 = 0;
4889 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4890 byte_count = 3 /* pad */ + params + count;
4891 pSMB->DataCount = cpu_to_le16(count);
4892 pSMB->ParameterCount = cpu_to_le16(params);
4893 pSMB->TotalDataCount = pSMB->DataCount;
4894 pSMB->TotalParameterCount = pSMB->ParameterCount;
4895 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4896 pSMB->DataOffset = cpu_to_le16(offset);
4898 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4899 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4901 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4902 pSMB->Reserved4 = 0;
4903 pSMB->hdr.smb_buf_length += byte_count;
4904 pSMB->ByteCount = cpu_to_le16(byte_count);
4905 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4906 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4908 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4910 /* Note: On -EAGAIN error only caller can retry on handle based calls
4911 since file handle passed in no longer valid */
4917 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4918 bool delete_file, __u16 fid, __u32 pid_of_opener)
4920 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4923 __u16 params, param_offset, offset, byte_count, count;
4925 cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4926 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4931 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4932 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4935 pSMB->MaxSetupCount = 0;
4939 pSMB->Reserved2 = 0;
4940 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4941 offset = param_offset + params;
4943 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4946 pSMB->MaxParameterCount = cpu_to_le16(2);
4947 /* BB find max SMB PDU from sess */
4948 pSMB->MaxDataCount = cpu_to_le16(1000);
4949 pSMB->SetupCount = 1;
4950 pSMB->Reserved3 = 0;
4951 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4952 byte_count = 3 /* pad */ + params + count;
4953 pSMB->DataCount = cpu_to_le16(count);
4954 pSMB->ParameterCount = cpu_to_le16(params);
4955 pSMB->TotalDataCount = pSMB->DataCount;
4956 pSMB->TotalParameterCount = pSMB->ParameterCount;
4957 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4958 pSMB->DataOffset = cpu_to_le16(offset);
4960 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4961 pSMB->Reserved4 = 0;
4962 pSMB->hdr.smb_buf_length += byte_count;
4963 pSMB->ByteCount = cpu_to_le16(byte_count);
4964 *data_offset = delete_file ? 1 : 0;
4965 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4967 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4973 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4974 const char *fileName, const FILE_BASIC_INFO *data,
4975 const struct nls_table *nls_codepage, int remap)
4977 TRANSACTION2_SPI_REQ *pSMB = NULL;
4978 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4981 int bytes_returned = 0;
4983 __u16 params, param_offset, offset, byte_count, count;
4985 cFYI(1, ("In SetTimes"));
4988 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4993 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4995 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4996 PATH_MAX, nls_codepage, remap);
4997 name_len++; /* trailing null */
4999 } else { /* BB improve the check for buffer overruns BB */
5000 name_len = strnlen(fileName, PATH_MAX);
5001 name_len++; /* trailing null */
5002 strncpy(pSMB->FileName, fileName, name_len);
5005 params = 6 + name_len;
5006 count = sizeof(FILE_BASIC_INFO);
5007 pSMB->MaxParameterCount = cpu_to_le16(2);
5008 /* BB find max SMB PDU from sess structure BB */
5009 pSMB->MaxDataCount = cpu_to_le16(1000);
5010 pSMB->MaxSetupCount = 0;
5014 pSMB->Reserved2 = 0;
5015 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5016 InformationLevel) - 4;
5017 offset = param_offset + params;
5018 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5019 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5020 pSMB->DataOffset = cpu_to_le16(offset);
5021 pSMB->SetupCount = 1;
5022 pSMB->Reserved3 = 0;
5023 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5024 byte_count = 3 /* pad */ + params + count;
5026 pSMB->DataCount = cpu_to_le16(count);
5027 pSMB->ParameterCount = cpu_to_le16(params);
5028 pSMB->TotalDataCount = pSMB->DataCount;
5029 pSMB->TotalParameterCount = pSMB->ParameterCount;
5030 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5031 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5033 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5034 pSMB->Reserved4 = 0;
5035 pSMB->hdr.smb_buf_length += byte_count;
5036 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5037 pSMB->ByteCount = cpu_to_le16(byte_count);
5038 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5039 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5041 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5043 cifs_buf_release(pSMB);
5051 /* Can not be used to set time stamps yet (due to old DOS time format) */
5052 /* Can be used to set attributes */
5053 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5054 handling it anyway and NT4 was what we thought it would be needed for
5055 Do not delete it until we prove whether needed for Win9x though */
5057 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5058 __u16 dos_attrs, const struct nls_table *nls_codepage)
5060 SETATTR_REQ *pSMB = NULL;
5061 SETATTR_RSP *pSMBr = NULL;
5066 cFYI(1, ("In SetAttrLegacy"));
5069 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5074 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5076 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5077 PATH_MAX, nls_codepage);
5078 name_len++; /* trailing null */
5080 } else { /* BB improve the check for buffer overruns BB */
5081 name_len = strnlen(fileName, PATH_MAX);
5082 name_len++; /* trailing null */
5083 strncpy(pSMB->fileName, fileName, name_len);
5085 pSMB->attr = cpu_to_le16(dos_attrs);
5086 pSMB->BufferFormat = 0x04;
5087 pSMB->hdr.smb_buf_length += name_len + 1;
5088 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5089 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5090 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5092 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5094 cifs_buf_release(pSMB);
5097 goto SetAttrLgcyRetry;
5101 #endif /* temporarily unneeded SetAttr legacy function */
5104 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5105 const struct cifs_unix_set_info_args *args,
5106 const struct nls_table *nls_codepage, int remap)
5108 TRANSACTION2_SPI_REQ *pSMB = NULL;
5109 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5112 int bytes_returned = 0;
5113 FILE_UNIX_BASIC_INFO *data_offset;
5114 __u16 params, param_offset, offset, count, byte_count;
5115 __u64 mode = args->mode;
5117 cFYI(1, ("In SetUID/GID/Mode"));
5119 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5124 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5126 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5127 PATH_MAX, nls_codepage, remap);
5128 name_len++; /* trailing null */
5130 } else { /* BB improve the check for buffer overruns BB */
5131 name_len = strnlen(fileName, PATH_MAX);
5132 name_len++; /* trailing null */
5133 strncpy(pSMB->FileName, fileName, name_len);
5136 params = 6 + name_len;
5137 count = sizeof(FILE_UNIX_BASIC_INFO);
5138 pSMB->MaxParameterCount = cpu_to_le16(2);
5139 /* BB find max SMB PDU from sess structure BB */
5140 pSMB->MaxDataCount = cpu_to_le16(1000);
5141 pSMB->MaxSetupCount = 0;
5145 pSMB->Reserved2 = 0;
5146 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5147 InformationLevel) - 4;
5148 offset = param_offset + params;
5150 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5152 memset(data_offset, 0, count);
5153 pSMB->DataOffset = cpu_to_le16(offset);
5154 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5155 pSMB->SetupCount = 1;
5156 pSMB->Reserved3 = 0;
5157 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5158 byte_count = 3 /* pad */ + params + count;
5159 pSMB->ParameterCount = cpu_to_le16(params);
5160 pSMB->DataCount = cpu_to_le16(count);
5161 pSMB->TotalParameterCount = pSMB->ParameterCount;
5162 pSMB->TotalDataCount = pSMB->DataCount;
5163 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5164 pSMB->Reserved4 = 0;
5165 pSMB->hdr.smb_buf_length += byte_count;
5166 /* Samba server ignores set of file size to zero due to bugs in some
5167 older clients, but we should be precise - we use SetFileSize to
5168 set file size and do not want to truncate file size to zero
5169 accidently as happened on one Samba server beta by putting
5170 zero instead of -1 here */
5171 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5172 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5173 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5174 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5175 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5176 data_offset->Uid = cpu_to_le64(args->uid);
5177 data_offset->Gid = cpu_to_le64(args->gid);
5178 /* better to leave device as zero when it is */
5179 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5180 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5181 data_offset->Permissions = cpu_to_le64(mode);
5184 data_offset->Type = cpu_to_le32(UNIX_FILE);
5185 else if (S_ISDIR(mode))
5186 data_offset->Type = cpu_to_le32(UNIX_DIR);
5187 else if (S_ISLNK(mode))
5188 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5189 else if (S_ISCHR(mode))
5190 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5191 else if (S_ISBLK(mode))
5192 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5193 else if (S_ISFIFO(mode))
5194 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5195 else if (S_ISSOCK(mode))
5196 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5199 pSMB->ByteCount = cpu_to_le16(byte_count);
5200 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5201 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5203 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5205 cifs_buf_release(pSMB);
5211 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5212 const int notify_subdirs, const __u16 netfid,
5213 __u32 filter, struct file *pfile, int multishot,
5214 const struct nls_table *nls_codepage)
5217 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5218 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5219 struct dir_notify_req *dnotify_req;
5222 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5223 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5228 pSMB->TotalParameterCount = 0 ;
5229 pSMB->TotalDataCount = 0;
5230 pSMB->MaxParameterCount = cpu_to_le32(2);
5231 /* BB find exact data count max from sess structure BB */
5232 pSMB->MaxDataCount = 0; /* same in little endian or be */
5233 /* BB VERIFY verify which is correct for above BB */
5234 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5235 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5237 pSMB->MaxSetupCount = 4;
5239 pSMB->ParameterOffset = 0;
5240 pSMB->DataCount = 0;
5241 pSMB->DataOffset = 0;
5242 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5243 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5244 pSMB->ParameterCount = pSMB->TotalParameterCount;
5246 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5247 pSMB->Reserved2 = 0;
5248 pSMB->CompletionFilter = cpu_to_le32(filter);
5249 pSMB->Fid = netfid; /* file handle always le */
5250 pSMB->ByteCount = 0;
5252 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5253 (struct smb_hdr *)pSMBr, &bytes_returned,
5256 cFYI(1, ("Error in Notify = %d", rc));
5258 /* Add file to outstanding requests */
5259 /* BB change to kmem cache alloc */
5260 dnotify_req = kmalloc(
5261 sizeof(struct dir_notify_req),
5264 dnotify_req->Pid = pSMB->hdr.Pid;
5265 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5266 dnotify_req->Mid = pSMB->hdr.Mid;
5267 dnotify_req->Tid = pSMB->hdr.Tid;
5268 dnotify_req->Uid = pSMB->hdr.Uid;
5269 dnotify_req->netfid = netfid;
5270 dnotify_req->pfile = pfile;
5271 dnotify_req->filter = filter;
5272 dnotify_req->multishot = multishot;
5273 spin_lock(&GlobalMid_Lock);
5274 list_add_tail(&dnotify_req->lhead,
5275 &GlobalDnotifyReqList);
5276 spin_unlock(&GlobalMid_Lock);
5280 cifs_buf_release(pSMB);
5283 #ifdef CONFIG_CIFS_XATTR
5285 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5286 const unsigned char *searchName,
5287 char *EAData, size_t buf_size,
5288 const struct nls_table *nls_codepage, int remap)
5290 /* BB assumes one setup word */
5291 TRANSACTION2_QPI_REQ *pSMB = NULL;
5292 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5296 struct fea *temp_fea;
5298 __u16 params, byte_count;
5300 cFYI(1, ("In Query All EAs path %s", searchName));
5302 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5307 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5309 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5310 PATH_MAX, nls_codepage, remap);
5311 name_len++; /* trailing null */
5313 } else { /* BB improve the check for buffer overruns BB */
5314 name_len = strnlen(searchName, PATH_MAX);
5315 name_len++; /* trailing null */
5316 strncpy(pSMB->FileName, searchName, name_len);
5319 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5320 pSMB->TotalDataCount = 0;
5321 pSMB->MaxParameterCount = cpu_to_le16(2);
5322 /* BB find exact max SMB PDU from sess structure BB */
5323 pSMB->MaxDataCount = cpu_to_le16(4000);
5324 pSMB->MaxSetupCount = 0;
5328 pSMB->Reserved2 = 0;
5329 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5330 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5331 pSMB->DataCount = 0;
5332 pSMB->DataOffset = 0;
5333 pSMB->SetupCount = 1;
5334 pSMB->Reserved3 = 0;
5335 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5336 byte_count = params + 1 /* pad */ ;
5337 pSMB->TotalParameterCount = cpu_to_le16(params);
5338 pSMB->ParameterCount = pSMB->TotalParameterCount;
5339 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5340 pSMB->Reserved4 = 0;
5341 pSMB->hdr.smb_buf_length += byte_count;
5342 pSMB->ByteCount = cpu_to_le16(byte_count);
5344 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5345 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5347 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5348 } else { /* decode response */
5349 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5351 /* BB also check enough total bytes returned */
5352 /* BB we need to improve the validity checking
5353 of these trans2 responses */
5354 if (rc || (pSMBr->ByteCount < 4))
5355 rc = -EIO; /* bad smb */
5356 /* else if (pFindData){
5357 memcpy((char *) pFindData,
5358 (char *) &pSMBr->hdr.Protocol +
5361 /* check that length of list is not more than bcc */
5362 /* check that each entry does not go beyond length
5364 /* check that each element of each entry does not
5365 go beyond end of list */
5366 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5367 struct fealist *ea_response_data;
5369 /* validate_trans2_offsets() */
5370 /* BB check if start of smb + data_offset > &bcc+ bcc */
5371 ea_response_data = (struct fealist *)
5372 (((char *) &pSMBr->hdr.Protocol) +
5374 name_len = le32_to_cpu(ea_response_data->list_len);
5375 cFYI(1, ("ea length %d", name_len));
5376 if (name_len <= 8) {
5377 /* returned EA size zeroed at top of function */
5378 cFYI(1, ("empty EA list returned from server"));
5380 /* account for ea list len */
5382 temp_fea = ea_response_data->list;
5383 temp_ptr = (char *)temp_fea;
5384 while (name_len > 0) {
5388 rc += temp_fea->name_len;
5389 /* account for prefix user. and trailing null */
5391 if (rc < (int)buf_size) {
5392 memcpy(EAData, "user.", 5);
5394 memcpy(EAData, temp_ptr,
5395 temp_fea->name_len);
5396 EAData += temp_fea->name_len;
5397 /* null terminate name */
5399 EAData = EAData + 1;
5400 } else if (buf_size == 0) {
5401 /* skip copy - calc size only */
5403 /* stop before overrun buffer */
5407 name_len -= temp_fea->name_len;
5408 temp_ptr += temp_fea->name_len;
5409 /* account for trailing null */
5413 le16_to_cpu(temp_fea->value_len);
5414 name_len -= value_len;
5415 temp_ptr += value_len;
5416 /* BB check that temp_ptr is still
5419 /* no trailing null to account for
5421 /* go on to next EA */
5422 temp_fea = (struct fea *)temp_ptr;
5427 cifs_buf_release(pSMB);
5434 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5435 const unsigned char *searchName, const unsigned char *ea_name,
5436 unsigned char *ea_value, size_t buf_size,
5437 const struct nls_table *nls_codepage, int remap)
5439 TRANSACTION2_QPI_REQ *pSMB = NULL;
5440 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5444 struct fea *temp_fea;
5446 __u16 params, byte_count;
5448 cFYI(1, ("In Query EA path %s", searchName));
5450 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5455 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5457 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5458 PATH_MAX, nls_codepage, remap);
5459 name_len++; /* trailing null */
5461 } else { /* BB improve the check for buffer overruns BB */
5462 name_len = strnlen(searchName, PATH_MAX);
5463 name_len++; /* trailing null */
5464 strncpy(pSMB->FileName, searchName, name_len);
5467 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5468 pSMB->TotalDataCount = 0;
5469 pSMB->MaxParameterCount = cpu_to_le16(2);
5470 /* BB find exact max SMB PDU from sess structure BB */
5471 pSMB->MaxDataCount = cpu_to_le16(4000);
5472 pSMB->MaxSetupCount = 0;
5476 pSMB->Reserved2 = 0;
5477 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5478 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5479 pSMB->DataCount = 0;
5480 pSMB->DataOffset = 0;
5481 pSMB->SetupCount = 1;
5482 pSMB->Reserved3 = 0;
5483 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5484 byte_count = params + 1 /* pad */ ;
5485 pSMB->TotalParameterCount = cpu_to_le16(params);
5486 pSMB->ParameterCount = pSMB->TotalParameterCount;
5487 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5488 pSMB->Reserved4 = 0;
5489 pSMB->hdr.smb_buf_length += byte_count;
5490 pSMB->ByteCount = cpu_to_le16(byte_count);
5492 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5493 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5495 cFYI(1, ("Send error in Query EA = %d", rc));
5496 } else { /* decode response */
5497 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5499 /* BB also check enough total bytes returned */
5500 /* BB we need to improve the validity checking
5501 of these trans2 responses */
5502 if (rc || (pSMBr->ByteCount < 4))
5503 rc = -EIO; /* bad smb */
5504 /* else if (pFindData){
5505 memcpy((char *) pFindData,
5506 (char *) &pSMBr->hdr.Protocol +
5509 /* check that length of list is not more than bcc */
5510 /* check that each entry does not go beyond length
5512 /* check that each element of each entry does not
5513 go beyond end of list */
5514 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5515 struct fealist *ea_response_data;
5517 /* validate_trans2_offsets() */
5518 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5519 ea_response_data = (struct fealist *)
5520 (((char *) &pSMBr->hdr.Protocol) +
5522 name_len = le32_to_cpu(ea_response_data->list_len);
5523 cFYI(1, ("ea length %d", name_len));
5524 if (name_len <= 8) {
5525 /* returned EA size zeroed at top of function */
5526 cFYI(1, ("empty EA list returned from server"));
5528 /* account for ea list len */
5530 temp_fea = ea_response_data->list;
5531 temp_ptr = (char *)temp_fea;
5532 /* loop through checking if we have a matching
5533 name and then return the associated value */
5534 while (name_len > 0) {
5539 le16_to_cpu(temp_fea->value_len);
5540 /* BB validate that value_len falls within SMB,
5541 even though maximum for name_len is 255 */
5542 if (memcmp(temp_fea->name, ea_name,
5543 temp_fea->name_len) == 0) {
5546 /* account for prefix user. and trailing null */
5547 if (rc <= (int)buf_size) {
5549 temp_fea->name+temp_fea->name_len+1,
5551 /* ea values, unlike ea
5554 } else if (buf_size == 0) {
5555 /* skip copy - calc size only */
5557 /* stop before overrun buffer */
5562 name_len -= temp_fea->name_len;
5563 temp_ptr += temp_fea->name_len;
5564 /* account for trailing null */
5567 name_len -= value_len;
5568 temp_ptr += value_len;
5569 /* No trailing null to account for in
5570 value_len. Go on to next EA */
5571 temp_fea = (struct fea *)temp_ptr;
5576 cifs_buf_release(pSMB);
5584 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5585 const char *ea_name, const void *ea_value,
5586 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5589 struct smb_com_transaction2_spi_req *pSMB = NULL;
5590 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5591 struct fealist *parm_data;
5594 int bytes_returned = 0;
5595 __u16 params, param_offset, byte_count, offset, count;
5597 cFYI(1, ("In SetEA"));
5599 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5604 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5606 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5607 PATH_MAX, nls_codepage, remap);
5608 name_len++; /* trailing null */
5610 } else { /* BB improve the check for buffer overruns BB */
5611 name_len = strnlen(fileName, PATH_MAX);
5612 name_len++; /* trailing null */
5613 strncpy(pSMB->FileName, fileName, name_len);
5616 params = 6 + name_len;
5618 /* done calculating parms using name_len of file name,
5619 now use name_len to calculate length of ea name
5620 we are going to create in the inode xattrs */
5621 if (ea_name == NULL)
5624 name_len = strnlen(ea_name, 255);
5626 count = sizeof(*parm_data) + ea_value_len + name_len;
5627 pSMB->MaxParameterCount = cpu_to_le16(2);
5628 /* BB find max SMB PDU from sess */
5629 pSMB->MaxDataCount = cpu_to_le16(1000);
5630 pSMB->MaxSetupCount = 0;
5634 pSMB->Reserved2 = 0;
5635 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5636 InformationLevel) - 4;
5637 offset = param_offset + params;
5638 pSMB->InformationLevel =
5639 cpu_to_le16(SMB_SET_FILE_EA);
5642 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5644 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5645 pSMB->DataOffset = cpu_to_le16(offset);
5646 pSMB->SetupCount = 1;
5647 pSMB->Reserved3 = 0;
5648 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5649 byte_count = 3 /* pad */ + params + count;
5650 pSMB->DataCount = cpu_to_le16(count);
5651 parm_data->list_len = cpu_to_le32(count);
5652 parm_data->list[0].EA_flags = 0;
5653 /* we checked above that name len is less than 255 */
5654 parm_data->list[0].name_len = (__u8)name_len;
5655 /* EA names are always ASCII */
5657 strncpy(parm_data->list[0].name, ea_name, name_len);
5658 parm_data->list[0].name[name_len] = 0;
5659 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5660 /* caller ensures that ea_value_len is less than 64K but
5661 we need to ensure that it fits within the smb */
5663 /*BB add length check to see if it would fit in
5664 negotiated SMB buffer size BB */
5665 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5667 memcpy(parm_data->list[0].name+name_len+1,
5668 ea_value, ea_value_len);
5670 pSMB->TotalDataCount = pSMB->DataCount;
5671 pSMB->ParameterCount = cpu_to_le16(params);
5672 pSMB->TotalParameterCount = pSMB->ParameterCount;
5673 pSMB->Reserved4 = 0;
5674 pSMB->hdr.smb_buf_length += byte_count;
5675 pSMB->ByteCount = cpu_to_le16(byte_count);
5676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5679 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5681 cifs_buf_release(pSMB);