4 * Copyright (C) International Business Machines Corp., 2002,2007
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>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #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 */
85 /* Mark as invalid, all open files on tree connections since they
86 were closed when session to server was lost */
87 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
89 struct cifsFileInfo *open_file = NULL;
90 struct list_head *tmp;
91 struct list_head *tmp1;
93 /* list all files open on tree connection and mark them invalid */
94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = TRUE;
101 write_unlock(&GlobalSMBSeslock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
106 /* If the return code is zero, this function must fill in request_buf pointer */
108 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
109 void **request_buf /* returned */)
113 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
114 check for tcp and smb session status done differently
115 for those three - in the calling routine */
117 if (tcon->tidStatus == CifsExiting) {
118 /* only tree disconnect, open, and write,
119 (and ulogoff which does not have tcon)
120 are allowed as we start force umount */
121 if ((smb_command != SMB_COM_WRITE_ANDX) &&
122 (smb_command != SMB_COM_OPEN_ANDX) &&
123 (smb_command != SMB_COM_TREE_DISCONNECT)) {
124 cFYI(1, ("can not send cmd %d while umounting",
129 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
130 (tcon->ses->server)) {
131 struct nls_table *nls_codepage;
132 /* Give Demultiplex thread up to 10 seconds to
133 reconnect, should be greater than cifs socket
134 timeout which is 7 seconds */
135 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
138 if (tcon->ses->server->tcpStatus == CifsNeedReconnect) {
139 /* on "soft" mounts we wait once */
140 if ((tcon->retry == FALSE) ||
141 (tcon->ses->status == CifsExiting)) {
142 cFYI(1, ("gave up waiting on "
143 "reconnect in smb_init"));
145 } /* else "hard" mount - keep retrying
146 until process is killed or server
147 comes back on-line */
148 } else /* TCP session is reestablished now */
152 nls_codepage = load_nls_default();
153 /* need to prevent multiple threads trying to
154 simultaneously reconnect the same SMB session */
155 down(&tcon->ses->sesSem);
156 if (tcon->ses->status == CifsNeedReconnect)
157 rc = cifs_setup_session(0, tcon->ses,
159 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
160 mark_open_files_invalid(tcon);
161 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
163 up(&tcon->ses->sesSem);
164 /* tell server which Unix caps we support */
165 if (tcon->ses->capabilities & CAP_UNIX)
166 reset_cifs_unix_caps(0 /* no xid */,
168 NULL /* we do not know sb */,
169 NULL /* no vol info */);
170 /* BB FIXME add code to check if wsize needs
171 update due to negotiated smb buffer size
174 atomic_inc(&tconInfoReconnectCount);
176 cFYI(1, ("reconnect tcon rc = %d", rc));
177 /* Removed call to reopen open files here.
178 It is safer (and faster) to reopen files
179 one at a time as needed in read and write */
181 /* Check if handle based operation so we
182 know whether we can continue or not without
183 returning to caller to reset file handle */
184 switch (smb_command) {
185 case SMB_COM_READ_ANDX:
186 case SMB_COM_WRITE_ANDX:
188 case SMB_COM_FIND_CLOSE2:
189 case SMB_COM_LOCKING_ANDX: {
190 unload_nls(nls_codepage);
195 up(&tcon->ses->sesSem);
197 unload_nls(nls_codepage);
206 *request_buf = cifs_small_buf_get();
207 if (*request_buf == NULL) {
208 /* BB should we add a retry in here if not a writepage? */
212 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
215 cifs_stats_inc(&tcon->num_smbs_sent);
221 small_smb_init_no_tc(const int smb_command, const int wct,
222 struct cifsSesInfo *ses, void **request_buf)
225 struct smb_hdr *buffer;
227 rc = small_smb_init(smb_command, wct, NULL, request_buf);
231 buffer = (struct smb_hdr *)*request_buf;
232 buffer->Mid = GetNextMid(ses->server);
233 if (ses->capabilities & CAP_UNICODE)
234 buffer->Flags2 |= SMBFLG2_UNICODE;
235 if (ses->capabilities & CAP_STATUS32)
236 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
238 /* uid, tid can stay at zero as set in header assemble */
240 /* BB add support for turning on the signing when
241 this function is used after 1st of session setup requests */
246 /* If the return code is zero, this function must fill in request_buf pointer */
248 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
249 void **request_buf /* returned */ ,
250 void **response_buf /* returned */ )
254 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
255 check for tcp and smb session status done differently
256 for those three - in the calling routine */
258 if (tcon->tidStatus == CifsExiting) {
259 /* only tree disconnect, open, and write,
260 (and ulogoff which does not have tcon)
261 are allowed as we start force umount */
262 if ((smb_command != SMB_COM_WRITE_ANDX) &&
263 (smb_command != SMB_COM_OPEN_ANDX) &&
264 (smb_command != SMB_COM_TREE_DISCONNECT)) {
265 cFYI(1, ("can not send cmd %d while umounting",
271 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
272 (tcon->ses->server)) {
273 struct nls_table *nls_codepage;
274 /* Give Demultiplex thread up to 10 seconds to
275 reconnect, should be greater than cifs socket
276 timeout which is 7 seconds */
277 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
278 wait_event_interruptible_timeout(tcon->ses->server->response_q,
279 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
280 if (tcon->ses->server->tcpStatus ==
282 /* on "soft" mounts we wait once */
283 if ((tcon->retry == FALSE) ||
284 (tcon->ses->status == CifsExiting)) {
285 cFYI(1, ("gave up waiting on "
286 "reconnect in smb_init"));
288 } /* else "hard" mount - keep retrying
289 until process is killed or server
291 } else /* TCP session is reestablished now */
294 nls_codepage = load_nls_default();
295 /* need to prevent multiple threads trying to
296 simultaneously reconnect the same SMB session */
297 down(&tcon->ses->sesSem);
298 if (tcon->ses->status == CifsNeedReconnect)
299 rc = cifs_setup_session(0, tcon->ses,
301 if (!rc && (tcon->tidStatus == CifsNeedReconnect)) {
302 mark_open_files_invalid(tcon);
303 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
305 up(&tcon->ses->sesSem);
306 /* tell server which Unix caps we support */
307 if (tcon->ses->capabilities & CAP_UNIX)
308 reset_cifs_unix_caps(0 /* no xid */,
310 NULL /* do not know sb */,
311 NULL /* no vol info */);
312 /* BB FIXME add code to check if wsize needs
313 update due to negotiated smb buffer size
316 atomic_inc(&tconInfoReconnectCount);
318 cFYI(1, ("reconnect tcon rc = %d", rc));
319 /* Removed call to reopen open files here.
320 It is safer (and faster) to reopen files
321 one at a time as needed in read and write */
323 /* Check if handle based operation so we
324 know whether we can continue or not without
325 returning to caller to reset file handle */
326 switch (smb_command) {
327 case SMB_COM_READ_ANDX:
328 case SMB_COM_WRITE_ANDX:
330 case SMB_COM_FIND_CLOSE2:
331 case SMB_COM_LOCKING_ANDX: {
332 unload_nls(nls_codepage);
337 up(&tcon->ses->sesSem);
339 unload_nls(nls_codepage);
348 *request_buf = cifs_buf_get();
349 if (*request_buf == NULL) {
350 /* BB should we add a retry in here if not a writepage? */
353 /* Although the original thought was we needed the response buf for */
354 /* potential retries of smb operations it turns out we can determine */
355 /* from the mid flags when the request buffer can be resent without */
356 /* having to use a second distinct buffer for the response */
358 *response_buf = *request_buf;
360 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
364 cifs_stats_inc(&tcon->num_smbs_sent);
369 static int validate_t2(struct smb_t2_rsp *pSMB)
375 /* check for plausible wct, bcc and t2 data and parm sizes */
376 /* check for parm and data offset going beyond end of smb */
377 if (pSMB->hdr.WordCount >= 10) {
378 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
379 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
380 /* check that bcc is at least as big as parms + data */
381 /* check that bcc is less than negotiated smb buffer */
382 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
383 if (total_size < 512) {
384 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
385 /* BCC le converted in SendReceive */
386 pBCC = (pSMB->hdr.WordCount * 2) +
387 sizeof(struct smb_hdr) +
389 if ((total_size <= (*(u16 *)pBCC)) &&
391 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
397 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
398 sizeof(struct smb_t2_rsp) + 16);
402 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
405 NEGOTIATE_RSP *pSMBr;
409 struct TCP_Server_Info *server;
411 unsigned int secFlags;
415 server = ses->server;
420 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
421 (void **) &pSMB, (void **) &pSMBr);
425 /* if any of auth flags (ie not sign or seal) are overriden use them */
426 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
427 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
428 else /* if override flags set only sign/seal OR them with global auth */
429 secFlags = extended_security | ses->overrideSecFlg;
431 cFYI(1, ("secFlags 0x%x", secFlags));
433 pSMB->hdr.Mid = GetNextMid(server);
434 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
435 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
436 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
439 for (i = 0; i < CIFS_NUM_PROT; i++) {
440 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
441 count += strlen(protocols[i].name) + 1;
442 /* null at end of source and target buffers anyway */
444 pSMB->hdr.smb_buf_length += count;
445 pSMB->ByteCount = cpu_to_le16(count);
447 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
448 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
452 dialect = le16_to_cpu(pSMBr->DialectIndex);
453 cFYI(1, ("Dialect: %d", dialect));
454 /* Check wct = 1 error case */
455 if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
456 /* core returns wct = 1, but we do not ask for core - otherwise
457 small wct just comes when dialect index is -1 indicating we
458 could not negotiate a common dialect */
461 #ifdef CONFIG_CIFS_WEAK_PW_HASH
462 } else if ((pSMBr->hdr.WordCount == 13)
463 && ((dialect == LANMAN_PROT)
464 || (dialect == LANMAN2_PROT))) {
466 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
468 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
469 (secFlags & CIFSSEC_MAY_PLNTXT))
470 server->secType = LANMAN;
472 cERROR(1, ("mount failed weak security disabled"
473 " in /proc/fs/cifs/SecurityFlags"));
477 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
478 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
479 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
480 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
481 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
482 /* even though we do not use raw we might as well set this
483 accurately, in case we ever find a need for it */
484 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
485 server->maxRw = 0xFF00;
486 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
488 server->maxRw = 0;/* we do not need to use raw anyway */
489 server->capabilities = CAP_MPX_MODE;
491 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
493 /* OS/2 often does not set timezone therefore
494 * we must use server time to calc time zone.
495 * Could deviate slightly from the right zone.
496 * Smallest defined timezone difference is 15 minutes
497 * (i.e. Nepal). Rounding up/down is done to match
500 int val, seconds, remain, result;
501 struct timespec ts, utc;
503 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
504 le16_to_cpu(rsp->SrvTime.Time));
505 cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
506 (int)ts.tv_sec, (int)utc.tv_sec,
507 (int)(utc.tv_sec - ts.tv_sec)));
508 val = (int)(utc.tv_sec - ts.tv_sec);
509 seconds = val < 0 ? -val : val;
510 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
511 remain = seconds % MIN_TZ_ADJ;
512 if (remain >= (MIN_TZ_ADJ / 2))
513 result += MIN_TZ_ADJ;
516 server->timeAdj = result;
518 server->timeAdj = (int)tmp;
519 server->timeAdj *= 60; /* also in seconds */
521 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
524 /* BB get server time for time conversions and add
525 code to use it and timezone since this is not UTC */
527 if (rsp->EncryptionKeyLength ==
528 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
529 memcpy(server->cryptKey, rsp->EncryptionKey,
530 CIFS_CRYPTO_KEY_SIZE);
531 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
532 rc = -EIO; /* need cryptkey unless plain text */
536 cFYI(1, ("LANMAN negotiated"));
537 /* we will not end up setting signing flags - as no signing
538 was in LANMAN and server did not return the flags on */
540 #else /* weak security disabled */
541 } else if (pSMBr->hdr.WordCount == 13) {
542 cERROR(1, ("mount failed, cifs module not built "
543 "with CIFS_WEAK_PW_HASH support"));
545 #endif /* WEAK_PW_HASH */
547 } else if (pSMBr->hdr.WordCount != 17) {
552 /* else wct == 17 NTLM */
553 server->secMode = pSMBr->SecurityMode;
554 if ((server->secMode & SECMODE_USER) == 0)
555 cFYI(1, ("share mode security"));
557 if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
558 #ifdef CONFIG_CIFS_WEAK_PW_HASH
559 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
560 #endif /* CIFS_WEAK_PW_HASH */
561 cERROR(1, ("Server requests plain text password"
562 " but client support disabled"));
564 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
565 server->secType = NTLMv2;
566 else if (secFlags & CIFSSEC_MAY_NTLM)
567 server->secType = NTLM;
568 else if (secFlags & CIFSSEC_MAY_NTLMV2)
569 server->secType = NTLMv2;
570 /* else krb5 ... any others ... */
572 /* one byte, so no need to convert this or EncryptionKeyLen from
574 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
575 /* probably no need to store and check maxvcs */
576 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
577 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
578 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
579 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
580 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
581 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
582 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
583 server->timeAdj *= 60;
584 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
585 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
586 CIFS_CRYPTO_KEY_SIZE);
587 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
588 && (pSMBr->EncryptionKeyLength == 0)) {
589 /* decode security blob */
590 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
591 rc = -EIO; /* no crypt key only if plain text pwd */
595 /* BB might be helpful to save off the domain of server here */
597 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
598 (server->capabilities & CAP_EXTENDED_SECURITY)) {
599 count = pSMBr->ByteCount;
602 else if (count == 16) {
603 server->secType = RawNTLMSSP;
604 if (server->socketUseCount.counter > 1) {
605 if (memcmp(server->server_GUID,
606 pSMBr->u.extended_response.
608 cFYI(1, ("server UID changed"));
609 memcpy(server->server_GUID,
610 pSMBr->u.extended_response.GUID,
614 memcpy(server->server_GUID,
615 pSMBr->u.extended_response.GUID, 16);
617 rc = decode_negTokenInit(pSMBr->u.extended_response.
622 /* BB Need to fill struct for sessetup here */
629 server->capabilities &= ~CAP_EXTENDED_SECURITY;
631 #ifdef CONFIG_CIFS_WEAK_PW_HASH
634 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
635 /* MUST_SIGN already includes the MAY_SIGN FLAG
636 so if this is zero it means that signing is disabled */
637 cFYI(1, ("Signing disabled"));
638 if (server->secMode & SECMODE_SIGN_REQUIRED)
639 cERROR(1, ("Server requires "
640 "/proc/fs/cifs/PacketSigningEnabled "
643 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
644 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
645 /* signing required */
646 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
647 if ((server->secMode &
648 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
650 ("signing required but server lacks support"));
653 server->secMode |= SECMODE_SIGN_REQUIRED;
655 /* signing optional ie CIFSSEC_MAY_SIGN */
656 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
658 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
662 cifs_buf_release(pSMB);
664 cFYI(1, ("negprot rc %d", rc));
669 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
671 struct smb_hdr *smb_buffer;
672 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
676 cFYI(1, ("In tree disconnect"));
678 * If last user of the connection and
679 * connection alive - disconnect it
680 * If this is the last connection on the server session disconnect it
681 * (and inside session disconnect we should check if tcp socket needs
682 * to be freed and kernel thread woken up).
685 down(&tcon->tconSem);
689 atomic_dec(&tcon->useCount);
690 if (atomic_read(&tcon->useCount) > 0) {
695 /* No need to return error on this operation if tid invalidated and
696 closed on server already e.g. due to tcp session crashing */
697 if (tcon->tidStatus == CifsNeedReconnect) {
702 if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
706 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
707 (void **)&smb_buffer);
712 smb_buffer_response = smb_buffer; /* BB removeme BB */
714 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
717 cFYI(1, ("Tree disconnect failed %d", rc));
720 cifs_small_buf_release(smb_buffer);
723 /* No need to return error on this operation if tid invalidated and
724 closed on server already e.g. due to tcp session crashing */
732 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
734 struct smb_hdr *smb_buffer_response;
735 LOGOFF_ANDX_REQ *pSMB;
739 cFYI(1, ("In SMBLogoff for session disconnect"));
745 atomic_dec(&ses->inUse);
746 if (atomic_read(&ses->inUse) > 0) {
750 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
756 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
759 pSMB->hdr.Mid = GetNextMid(ses->server);
761 if (ses->server->secMode &
762 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
763 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
766 pSMB->hdr.Uid = ses->Suid;
768 pSMB->AndXCommand = 0xFF;
769 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
770 smb_buffer_response, &length, 0);
772 atomic_dec(&ses->server->socketUseCount);
773 if (atomic_read(&ses->server->socketUseCount) == 0) {
774 spin_lock(&GlobalMid_Lock);
775 ses->server->tcpStatus = CifsExiting;
776 spin_unlock(&GlobalMid_Lock);
781 cifs_small_buf_release(pSMB);
783 /* if session dead then we do not need to do ulogoff,
784 since server closed smb session, no sense reporting
792 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
793 __u16 type, const struct nls_table *nls_codepage, int remap)
795 TRANSACTION2_SPI_REQ *pSMB = NULL;
796 TRANSACTION2_SPI_RSP *pSMBr = NULL;
797 struct unlink_psx_rq *pRqD;
800 int bytes_returned = 0;
801 __u16 params, param_offset, offset, byte_count;
803 cFYI(1, ("In POSIX delete"));
805 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
810 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
812 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
813 PATH_MAX, nls_codepage, remap);
814 name_len++; /* trailing null */
816 } else { /* BB add path length overrun check */
817 name_len = strnlen(fileName, PATH_MAX);
818 name_len++; /* trailing null */
819 strncpy(pSMB->FileName, fileName, name_len);
822 params = 6 + name_len;
823 pSMB->MaxParameterCount = cpu_to_le16(2);
824 pSMB->MaxDataCount = 0; /* BB double check this with jra */
825 pSMB->MaxSetupCount = 0;
830 param_offset = offsetof(struct smb_com_transaction2_spi_req,
831 InformationLevel) - 4;
832 offset = param_offset + params;
834 /* Setup pointer to Request Data (inode type) */
835 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
836 pRqD->type = cpu_to_le16(type);
837 pSMB->ParameterOffset = cpu_to_le16(param_offset);
838 pSMB->DataOffset = cpu_to_le16(offset);
839 pSMB->SetupCount = 1;
841 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
842 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
844 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
845 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
846 pSMB->ParameterCount = cpu_to_le16(params);
847 pSMB->TotalParameterCount = pSMB->ParameterCount;
848 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
850 pSMB->hdr.smb_buf_length += byte_count;
851 pSMB->ByteCount = cpu_to_le16(byte_count);
852 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
853 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
855 cFYI(1, ("Posix delete returned %d", rc));
857 cifs_buf_release(pSMB);
859 cifs_stats_inc(&tcon->num_deletes);
868 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
869 const struct nls_table *nls_codepage, int remap)
871 DELETE_FILE_REQ *pSMB = NULL;
872 DELETE_FILE_RSP *pSMBr = NULL;
878 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
883 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
885 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
886 PATH_MAX, nls_codepage, remap);
887 name_len++; /* trailing null */
889 } else { /* BB improve check for buffer overruns BB */
890 name_len = strnlen(fileName, PATH_MAX);
891 name_len++; /* trailing null */
892 strncpy(pSMB->fileName, fileName, name_len);
894 pSMB->SearchAttributes =
895 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
896 pSMB->BufferFormat = 0x04;
897 pSMB->hdr.smb_buf_length += name_len + 1;
898 pSMB->ByteCount = cpu_to_le16(name_len + 1);
899 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
900 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
901 cifs_stats_inc(&tcon->num_deletes);
903 cFYI(1, ("Error in RMFile = %d", rc));
906 cifs_buf_release(pSMB);
914 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
915 const struct nls_table *nls_codepage, int remap)
917 DELETE_DIRECTORY_REQ *pSMB = NULL;
918 DELETE_DIRECTORY_RSP *pSMBr = NULL;
923 cFYI(1, ("In CIFSSMBRmDir"));
925 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
930 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
931 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
932 PATH_MAX, nls_codepage, remap);
933 name_len++; /* trailing null */
935 } else { /* BB improve check for buffer overruns BB */
936 name_len = strnlen(dirName, PATH_MAX);
937 name_len++; /* trailing null */
938 strncpy(pSMB->DirName, dirName, name_len);
941 pSMB->BufferFormat = 0x04;
942 pSMB->hdr.smb_buf_length += name_len + 1;
943 pSMB->ByteCount = cpu_to_le16(name_len + 1);
944 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
945 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
946 cifs_stats_inc(&tcon->num_rmdirs);
948 cFYI(1, ("Error in RMDir = %d", rc));
951 cifs_buf_release(pSMB);
958 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
959 const char *name, const struct nls_table *nls_codepage, int remap)
962 CREATE_DIRECTORY_REQ *pSMB = NULL;
963 CREATE_DIRECTORY_RSP *pSMBr = NULL;
967 cFYI(1, ("In CIFSSMBMkDir"));
969 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
974 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
975 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
976 PATH_MAX, nls_codepage, remap);
977 name_len++; /* trailing null */
979 } else { /* BB improve check for buffer overruns BB */
980 name_len = strnlen(name, PATH_MAX);
981 name_len++; /* trailing null */
982 strncpy(pSMB->DirName, name, name_len);
985 pSMB->BufferFormat = 0x04;
986 pSMB->hdr.smb_buf_length += name_len + 1;
987 pSMB->ByteCount = cpu_to_le16(name_len + 1);
988 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
989 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
990 cifs_stats_inc(&tcon->num_mkdirs);
992 cFYI(1, ("Error in Mkdir = %d", rc));
995 cifs_buf_release(pSMB);
1002 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1003 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
1004 __u32 *pOplock, const char *name,
1005 const struct nls_table *nls_codepage, int remap)
1007 TRANSACTION2_SPI_REQ *pSMB = NULL;
1008 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1011 int bytes_returned = 0;
1012 __u16 params, param_offset, offset, byte_count, count;
1013 OPEN_PSX_REQ * pdata;
1014 OPEN_PSX_RSP * psx_rsp;
1016 cFYI(1, ("In POSIX Create"));
1018 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1023 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1025 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1026 PATH_MAX, nls_codepage, remap);
1027 name_len++; /* trailing null */
1029 } else { /* BB improve the check for buffer overruns BB */
1030 name_len = strnlen(name, PATH_MAX);
1031 name_len++; /* trailing null */
1032 strncpy(pSMB->FileName, name, name_len);
1035 params = 6 + name_len;
1036 count = sizeof(OPEN_PSX_REQ);
1037 pSMB->MaxParameterCount = cpu_to_le16(2);
1038 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1039 pSMB->MaxSetupCount = 0;
1043 pSMB->Reserved2 = 0;
1044 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1045 InformationLevel) - 4;
1046 offset = param_offset + params;
1047 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1048 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
1049 pdata->Permissions = cpu_to_le64(mode);
1050 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1051 pdata->OpenFlags = cpu_to_le32(*pOplock);
1052 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1053 pSMB->DataOffset = cpu_to_le16(offset);
1054 pSMB->SetupCount = 1;
1055 pSMB->Reserved3 = 0;
1056 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1057 byte_count = 3 /* pad */ + params + count;
1059 pSMB->DataCount = cpu_to_le16(count);
1060 pSMB->ParameterCount = cpu_to_le16(params);
1061 pSMB->TotalDataCount = pSMB->DataCount;
1062 pSMB->TotalParameterCount = pSMB->ParameterCount;
1063 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1064 pSMB->Reserved4 = 0;
1065 pSMB->hdr.smb_buf_length += byte_count;
1066 pSMB->ByteCount = cpu_to_le16(byte_count);
1067 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1068 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1070 cFYI(1, ("Posix create returned %d", rc));
1071 goto psx_create_err;
1074 cFYI(1, ("copying inode info"));
1075 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1077 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1078 rc = -EIO; /* bad smb */
1079 goto psx_create_err;
1082 /* copy return information to pRetData */
1083 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1084 + le16_to_cpu(pSMBr->t2.DataOffset));
1086 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1088 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1089 /* Let caller know file was created so we can set the mode. */
1090 /* Do we care about the CreateAction in any other cases? */
1091 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1092 *pOplock |= CIFS_CREATE_ACTION;
1093 /* check to make sure response data is there */
1094 if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
1095 pRetData->Type = -1; /* unknown */
1096 #ifdef CONFIG_CIFS_DEBUG2
1097 cFYI(1, ("unknown type"));
1100 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1101 + sizeof(FILE_UNIX_BASIC_INFO)) {
1102 cERROR(1, ("Open response data too small"));
1103 pRetData->Type = -1;
1104 goto psx_create_err;
1106 memcpy((char *) pRetData,
1107 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1108 sizeof (FILE_UNIX_BASIC_INFO));
1112 cifs_buf_release(pSMB);
1114 cifs_stats_inc(&tcon->num_mkdirs);
1122 static __u16 convert_disposition(int disposition)
1126 switch (disposition) {
1127 case FILE_SUPERSEDE:
1128 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1131 ofun = SMBOPEN_OAPPEND;
1134 ofun = SMBOPEN_OCREATE;
1137 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1139 case FILE_OVERWRITE:
1140 ofun = SMBOPEN_OTRUNC;
1142 case FILE_OVERWRITE_IF:
1143 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1146 cFYI(1, ("unknown disposition %d", disposition));
1147 ofun = SMBOPEN_OAPPEND; /* regular open */
1153 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1154 const char *fileName, const int openDisposition,
1155 const int access_flags, const int create_options, __u16 * netfid,
1156 int *pOplock, FILE_ALL_INFO * pfile_info,
1157 const struct nls_table *nls_codepage, int remap)
1160 OPENX_REQ *pSMB = NULL;
1161 OPENX_RSP *pSMBr = NULL;
1167 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1172 pSMB->AndXCommand = 0xFF; /* none */
1174 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1175 count = 1; /* account for one byte pad to word boundary */
1177 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1178 fileName, PATH_MAX, nls_codepage, remap);
1179 name_len++; /* trailing null */
1181 } else { /* BB improve check for buffer overruns BB */
1182 count = 0; /* no pad */
1183 name_len = strnlen(fileName, PATH_MAX);
1184 name_len++; /* trailing null */
1185 strncpy(pSMB->fileName, fileName, name_len);
1187 if (*pOplock & REQ_OPLOCK)
1188 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1189 else if (*pOplock & REQ_BATCHOPLOCK) {
1190 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1192 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1193 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1199 pSMB->Mode = cpu_to_le16(2);
1200 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1201 /* set file as system file if special file such
1202 as fifo and server expecting SFU style and
1203 no Unix extensions */
1205 if (create_options & CREATE_OPTION_SPECIAL)
1206 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1208 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1210 /* if ((omode & S_IWUGO) == 0)
1211 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1212 /* Above line causes problems due to vfs splitting create into two
1213 pieces - need to set mode after file created not while it is
1217 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1218 CREATE_OPTIONS_MASK); */
1219 /* BB FIXME END BB */
1221 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1222 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1224 pSMB->hdr.smb_buf_length += count;
1226 pSMB->ByteCount = cpu_to_le16(count);
1227 /* long_op set to 1 to allow for oplock break timeouts */
1228 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1229 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1230 cifs_stats_inc(&tcon->num_opens);
1232 cFYI(1, ("Error in Open = %d", rc));
1234 /* BB verify if wct == 15 */
1236 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1238 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1239 /* Let caller know file was created so we can set the mode. */
1240 /* Do we care about the CreateAction in any other cases? */
1242 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1243 *pOplock |= CIFS_CREATE_ACTION; */
1247 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1248 pfile_info->LastAccessTime = 0; /* BB fixme */
1249 pfile_info->LastWriteTime = 0; /* BB fixme */
1250 pfile_info->ChangeTime = 0; /* BB fixme */
1251 pfile_info->Attributes =
1252 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1253 /* the file_info buf is endian converted by caller */
1254 pfile_info->AllocationSize =
1255 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1256 pfile_info->EndOfFile = pfile_info->AllocationSize;
1257 pfile_info->NumberOfLinks = cpu_to_le32(1);
1261 cifs_buf_release(pSMB);
1268 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1269 const char *fileName, const int openDisposition,
1270 const int access_flags, const int create_options, __u16 * netfid,
1271 int *pOplock, FILE_ALL_INFO * pfile_info,
1272 const struct nls_table *nls_codepage, int remap)
1275 OPEN_REQ *pSMB = NULL;
1276 OPEN_RSP *pSMBr = NULL;
1282 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1287 pSMB->AndXCommand = 0xFF; /* none */
1289 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1290 count = 1; /* account for one byte pad to word boundary */
1292 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1293 fileName, PATH_MAX, nls_codepage, remap);
1294 name_len++; /* trailing null */
1296 pSMB->NameLength = cpu_to_le16(name_len);
1297 } else { /* BB improve check for buffer overruns BB */
1298 count = 0; /* no pad */
1299 name_len = strnlen(fileName, PATH_MAX);
1300 name_len++; /* trailing null */
1301 pSMB->NameLength = cpu_to_le16(name_len);
1302 strncpy(pSMB->fileName, fileName, name_len);
1304 if (*pOplock & REQ_OPLOCK)
1305 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1306 else if (*pOplock & REQ_BATCHOPLOCK) {
1307 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1309 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1310 pSMB->AllocationSize = 0;
1311 /* set file as system file if special file such
1312 as fifo and server expecting SFU style and
1313 no Unix extensions */
1314 if (create_options & CREATE_OPTION_SPECIAL)
1315 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1317 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1318 /* XP does not handle ATTR_POSIX_SEMANTICS */
1319 /* but it helps speed up case sensitive checks for other
1320 servers such as Samba */
1321 if (tcon->ses->capabilities & CAP_UNIX)
1322 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1324 /* if ((omode & S_IWUGO) == 0)
1325 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1326 /* Above line causes problems due to vfs splitting create into two
1327 pieces - need to set mode after file created not while it is
1329 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1330 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1331 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1332 /* BB Expirement with various impersonation levels and verify */
1333 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1334 pSMB->SecurityFlags =
1335 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1338 pSMB->hdr.smb_buf_length += count;
1340 pSMB->ByteCount = cpu_to_le16(count);
1341 /* long_op set to 1 to allow for oplock break timeouts */
1342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1343 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1344 cifs_stats_inc(&tcon->num_opens);
1346 cFYI(1, ("Error in Open = %d", rc));
1348 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1349 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1350 /* Let caller know file was created so we can set the mode. */
1351 /* Do we care about the CreateAction in any other cases? */
1352 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1353 *pOplock |= CIFS_CREATE_ACTION;
1355 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1356 36 /* CreationTime to Attributes */);
1357 /* the file_info buf is endian converted by caller */
1358 pfile_info->AllocationSize = pSMBr->AllocationSize;
1359 pfile_info->EndOfFile = pSMBr->EndOfFile;
1360 pfile_info->NumberOfLinks = cpu_to_le32(1);
1364 cifs_buf_release(pSMB);
1371 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1372 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1373 char **buf, int *pbuf_type)
1376 READ_REQ *pSMB = NULL;
1377 READ_RSP *pSMBr = NULL;
1378 char *pReadData = NULL;
1380 int resp_buf_type = 0;
1383 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1384 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1387 wct = 10; /* old style read */
1390 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1394 /* tcon and ses pointer are checked in smb_init */
1395 if (tcon->ses->server == NULL)
1396 return -ECONNABORTED;
1398 pSMB->AndXCommand = 0xFF; /* none */
1400 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1402 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1403 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1406 pSMB->Remaining = 0;
1407 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1408 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1410 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1412 /* old style read */
1413 struct smb_com_readx_req *pSMBW =
1414 (struct smb_com_readx_req *)pSMB;
1415 pSMBW->ByteCount = 0;
1418 iov[0].iov_base = (char *)pSMB;
1419 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1420 rc = SendReceive2(xid, tcon->ses, iov,
1423 cifs_stats_inc(&tcon->num_reads);
1424 pSMBr = (READ_RSP *)iov[0].iov_base;
1426 cERROR(1, ("Send error in read = %d", rc));
1428 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1429 data_length = data_length << 16;
1430 data_length += le16_to_cpu(pSMBr->DataLength);
1431 *nbytes = data_length;
1433 /*check that DataLength would not go beyond end of SMB */
1434 if ((data_length > CIFSMaxBufSize)
1435 || (data_length > count)) {
1436 cFYI(1, ("bad length %d for count %d",
1437 data_length, count));
1441 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1442 le16_to_cpu(pSMBr->DataOffset);
1443 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1444 cERROR(1,("Faulting on read rc = %d",rc));
1446 }*/ /* can not use copy_to_user when using page cache*/
1448 memcpy(*buf, pReadData, data_length);
1452 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1454 if (resp_buf_type == CIFS_SMALL_BUFFER)
1455 cifs_small_buf_release(iov[0].iov_base);
1456 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1457 cifs_buf_release(iov[0].iov_base);
1458 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1459 /* return buffer to caller to free */
1460 *buf = iov[0].iov_base;
1461 if (resp_buf_type == CIFS_SMALL_BUFFER)
1462 *pbuf_type = CIFS_SMALL_BUFFER;
1463 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1464 *pbuf_type = CIFS_LARGE_BUFFER;
1465 } /* else no valid buffer on return - leave as null */
1467 /* Note: On -EAGAIN error only caller can retry on handle based calls
1468 since file handle passed in no longer valid */
1474 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1475 const int netfid, const unsigned int count,
1476 const __u64 offset, unsigned int *nbytes, const char *buf,
1477 const char __user *ubuf, const int long_op)
1480 WRITE_REQ *pSMB = NULL;
1481 WRITE_RSP *pSMBr = NULL;
1482 int bytes_returned, wct;
1486 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1487 if (tcon->ses == NULL)
1488 return -ECONNABORTED;
1490 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1495 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1499 /* tcon and ses pointer are checked in smb_init */
1500 if (tcon->ses->server == NULL)
1501 return -ECONNABORTED;
1503 pSMB->AndXCommand = 0xFF; /* none */
1505 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1507 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1508 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1511 pSMB->Reserved = 0xFFFFFFFF;
1512 pSMB->WriteMode = 0;
1513 pSMB->Remaining = 0;
1515 /* Can increase buffer size if buffer is big enough in some cases ie we
1516 can send more if LARGE_WRITE_X capability returned by the server and if
1517 our buffer is big enough or if we convert to iovecs on socket writes
1518 and eliminate the copy to the CIFS buffer */
1519 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1520 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1522 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1526 if (bytes_sent > count)
1529 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1531 memcpy(pSMB->Data, buf, bytes_sent);
1533 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1534 cifs_buf_release(pSMB);
1537 } else if (count != 0) {
1539 cifs_buf_release(pSMB);
1541 } /* else setting file size with write of zero bytes */
1543 byte_count = bytes_sent + 1; /* pad */
1544 else /* wct == 12 */ {
1545 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1547 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1548 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1549 pSMB->hdr.smb_buf_length += byte_count;
1552 pSMB->ByteCount = cpu_to_le16(byte_count);
1553 else { /* old style write has byte count 4 bytes earlier
1555 struct smb_com_writex_req *pSMBW =
1556 (struct smb_com_writex_req *)pSMB;
1557 pSMBW->ByteCount = cpu_to_le16(byte_count);
1560 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1561 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1562 cifs_stats_inc(&tcon->num_writes);
1564 cFYI(1, ("Send error in write = %d", rc));
1567 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1568 *nbytes = (*nbytes) << 16;
1569 *nbytes += le16_to_cpu(pSMBr->Count);
1572 cifs_buf_release(pSMB);
1574 /* Note: On -EAGAIN error only caller can retry on handle based calls
1575 since file handle passed in no longer valid */
1581 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1582 const int netfid, const unsigned int count,
1583 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1584 int n_vec, const int long_op)
1587 WRITE_REQ *pSMB = NULL;
1590 int resp_buf_type = 0;
1592 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1594 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1598 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1601 /* tcon and ses pointer are checked in smb_init */
1602 if (tcon->ses->server == NULL)
1603 return -ECONNABORTED;
1605 pSMB->AndXCommand = 0xFF; /* none */
1607 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1609 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1610 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1612 pSMB->Reserved = 0xFFFFFFFF;
1613 pSMB->WriteMode = 0;
1614 pSMB->Remaining = 0;
1617 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1619 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1620 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1621 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1623 pSMB->hdr.smb_buf_length += count+1;
1624 else /* wct == 12 */
1625 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1627 pSMB->ByteCount = cpu_to_le16(count + 1);
1628 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1629 struct smb_com_writex_req *pSMBW =
1630 (struct smb_com_writex_req *)pSMB;
1631 pSMBW->ByteCount = cpu_to_le16(count + 5);
1633 iov[0].iov_base = pSMB;
1635 iov[0].iov_len = smb_hdr_len + 4;
1636 else /* wct == 12 pad bigger by four bytes */
1637 iov[0].iov_len = smb_hdr_len + 8;
1640 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1642 cifs_stats_inc(&tcon->num_writes);
1644 cFYI(1, ("Send error Write2 = %d", rc));
1646 } else if (resp_buf_type == 0) {
1647 /* presumably this can not happen, but best to be safe */
1651 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1652 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1653 *nbytes = (*nbytes) << 16;
1654 *nbytes += le16_to_cpu(pSMBr->Count);
1657 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1658 if (resp_buf_type == CIFS_SMALL_BUFFER)
1659 cifs_small_buf_release(iov[0].iov_base);
1660 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1661 cifs_buf_release(iov[0].iov_base);
1663 /* Note: On -EAGAIN error only caller can retry on handle based calls
1664 since file handle passed in no longer valid */
1671 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1672 const __u16 smb_file_id, const __u64 len,
1673 const __u64 offset, const __u32 numUnlock,
1674 const __u32 numLock, const __u8 lockType, const int waitFlag)
1677 LOCK_REQ *pSMB = NULL;
1678 LOCK_RSP *pSMBr = NULL;
1683 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1684 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1689 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1691 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1692 timeout = -1; /* no response expected */
1694 } else if (waitFlag == TRUE) {
1695 timeout = 3; /* blocking operation, no timeout */
1696 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1701 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1702 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1703 pSMB->LockType = lockType;
1704 pSMB->AndXCommand = 0xFF; /* none */
1705 pSMB->Fid = smb_file_id; /* netfid stays le */
1707 if ((numLock != 0) || (numUnlock != 0)) {
1708 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1709 /* BB where to store pid high? */
1710 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1711 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1712 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1713 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1714 count = sizeof(LOCKING_ANDX_RANGE);
1719 pSMB->hdr.smb_buf_length += count;
1720 pSMB->ByteCount = cpu_to_le16(count);
1723 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1724 (struct smb_hdr *) pSMBr, &bytes_returned);
1726 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1727 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1729 cifs_stats_inc(&tcon->num_locks);
1731 cFYI(1, ("Send error in Lock = %d", rc));
1733 cifs_small_buf_release(pSMB);
1735 /* Note: On -EAGAIN error only caller can retry on handle based calls
1736 since file handle passed in no longer valid */
1741 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1742 const __u16 smb_file_id, const int get_flag, const __u64 len,
1743 struct file_lock *pLockData, const __u16 lock_type,
1746 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1747 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1748 struct cifs_posix_lock *parm_data;
1751 int bytes_returned = 0;
1752 __u16 params, param_offset, offset, byte_count, count;
1754 cFYI(1, ("Posix Lock"));
1756 if (pLockData == NULL)
1759 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1764 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1767 pSMB->MaxSetupCount = 0;
1770 pSMB->Reserved2 = 0;
1771 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1772 offset = param_offset + params;
1774 count = sizeof(struct cifs_posix_lock);
1775 pSMB->MaxParameterCount = cpu_to_le16(2);
1776 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1777 pSMB->SetupCount = 1;
1778 pSMB->Reserved3 = 0;
1780 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1782 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1783 byte_count = 3 /* pad */ + params + count;
1784 pSMB->DataCount = cpu_to_le16(count);
1785 pSMB->ParameterCount = cpu_to_le16(params);
1786 pSMB->TotalDataCount = pSMB->DataCount;
1787 pSMB->TotalParameterCount = pSMB->ParameterCount;
1788 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1789 parm_data = (struct cifs_posix_lock *)
1790 (((char *) &pSMB->hdr.Protocol) + offset);
1792 parm_data->lock_type = cpu_to_le16(lock_type);
1794 timeout = 3; /* blocking operation, no timeout */
1795 parm_data->lock_flags = cpu_to_le16(1);
1796 pSMB->Timeout = cpu_to_le32(-1);
1800 parm_data->pid = cpu_to_le32(current->tgid);
1801 parm_data->start = cpu_to_le64(pLockData->fl_start);
1802 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1804 pSMB->DataOffset = cpu_to_le16(offset);
1805 pSMB->Fid = smb_file_id;
1806 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1807 pSMB->Reserved4 = 0;
1808 pSMB->hdr.smb_buf_length += byte_count;
1809 pSMB->ByteCount = cpu_to_le16(byte_count);
1811 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1812 (struct smb_hdr *) pSMBr, &bytes_returned);
1814 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1815 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1819 cFYI(1, ("Send error in Posix Lock = %d", rc));
1820 } else if (get_flag) {
1821 /* lock structure can be returned on get */
1824 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1826 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1827 rc = -EIO; /* bad smb */
1830 if (pLockData == NULL) {
1834 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1835 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1836 if (data_count < sizeof(struct cifs_posix_lock)) {
1840 parm_data = (struct cifs_posix_lock *)
1841 ((char *)&pSMBr->hdr.Protocol + data_offset);
1842 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1843 pLockData->fl_type = F_UNLCK;
1848 cifs_small_buf_release(pSMB);
1850 /* Note: On -EAGAIN error only caller can retry on handle based calls
1851 since file handle passed in no longer valid */
1858 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1861 CLOSE_REQ *pSMB = NULL;
1862 CLOSE_RSP *pSMBr = NULL;
1864 cFYI(1, ("In CIFSSMBClose"));
1866 /* do not retry on dead session on close */
1867 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1873 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1875 pSMB->FileID = (__u16) smb_file_id;
1876 pSMB->LastWriteTime = 0xFFFFFFFF;
1877 pSMB->ByteCount = 0;
1878 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1879 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1880 cifs_stats_inc(&tcon->num_closes);
1883 /* EINTR is expected when user ctl-c to kill app */
1884 cERROR(1, ("Send error in Close = %d", rc));
1888 cifs_small_buf_release(pSMB);
1890 /* Since session is dead, file will be closed on server already */
1898 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1899 const char *fromName, const char *toName,
1900 const struct nls_table *nls_codepage, int remap)
1903 RENAME_REQ *pSMB = NULL;
1904 RENAME_RSP *pSMBr = NULL;
1906 int name_len, name_len2;
1909 cFYI(1, ("In CIFSSMBRename"));
1911 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1916 pSMB->BufferFormat = 0x04;
1917 pSMB->SearchAttributes =
1918 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1921 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1923 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1924 PATH_MAX, nls_codepage, remap);
1925 name_len++; /* trailing null */
1927 pSMB->OldFileName[name_len] = 0x04; /* pad */
1928 /* protocol requires ASCII signature byte on Unicode string */
1929 pSMB->OldFileName[name_len + 1] = 0x00;
1931 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1932 toName, PATH_MAX, nls_codepage, remap);
1933 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1934 name_len2 *= 2; /* convert to bytes */
1935 } else { /* BB improve the check for buffer overruns BB */
1936 name_len = strnlen(fromName, PATH_MAX);
1937 name_len++; /* trailing null */
1938 strncpy(pSMB->OldFileName, fromName, name_len);
1939 name_len2 = strnlen(toName, PATH_MAX);
1940 name_len2++; /* trailing null */
1941 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1942 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1943 name_len2++; /* trailing null */
1944 name_len2++; /* signature byte */
1947 count = 1 /* 1st signature byte */ + name_len + name_len2;
1948 pSMB->hdr.smb_buf_length += count;
1949 pSMB->ByteCount = cpu_to_le16(count);
1951 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1952 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1953 cifs_stats_inc(&tcon->num_renames);
1955 cFYI(1, ("Send error in rename = %d", rc));
1958 cifs_buf_release(pSMB);
1966 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1967 int netfid, char *target_name,
1968 const struct nls_table *nls_codepage, int remap)
1970 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1971 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1972 struct set_file_rename *rename_info;
1974 char dummy_string[30];
1976 int bytes_returned = 0;
1978 __u16 params, param_offset, offset, count, byte_count;
1980 cFYI(1, ("Rename to File by handle"));
1981 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1987 pSMB->MaxSetupCount = 0;
1991 pSMB->Reserved2 = 0;
1992 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1993 offset = param_offset + params;
1995 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1996 rename_info = (struct set_file_rename *) data_offset;
1997 pSMB->MaxParameterCount = cpu_to_le16(2);
1998 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1999 pSMB->SetupCount = 1;
2000 pSMB->Reserved3 = 0;
2001 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2002 byte_count = 3 /* pad */ + params;
2003 pSMB->ParameterCount = cpu_to_le16(params);
2004 pSMB->TotalParameterCount = pSMB->ParameterCount;
2005 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2006 pSMB->DataOffset = cpu_to_le16(offset);
2007 /* construct random name ".cifs_tmp<inodenum><mid>" */
2008 rename_info->overwrite = cpu_to_le32(1);
2009 rename_info->root_fid = 0;
2010 /* unicode only call */
2011 if (target_name == NULL) {
2012 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2013 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2014 dummy_string, 24, nls_codepage, remap);
2016 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2017 target_name, PATH_MAX, nls_codepage,
2020 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2021 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
2022 byte_count += count;
2023 pSMB->DataCount = cpu_to_le16(count);
2024 pSMB->TotalDataCount = pSMB->DataCount;
2026 pSMB->InformationLevel =
2027 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2028 pSMB->Reserved4 = 0;
2029 pSMB->hdr.smb_buf_length += byte_count;
2030 pSMB->ByteCount = cpu_to_le16(byte_count);
2031 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2032 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2033 cifs_stats_inc(&pTcon->num_t2renames);
2035 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2038 cifs_buf_release(pSMB);
2040 /* Note: On -EAGAIN error only caller can retry on handle based calls
2041 since file handle passed in no longer valid */
2047 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2048 const __u16 target_tid, const char *toName, const int flags,
2049 const struct nls_table *nls_codepage, int remap)
2052 COPY_REQ *pSMB = NULL;
2053 COPY_RSP *pSMBr = NULL;
2055 int name_len, name_len2;
2058 cFYI(1, ("In CIFSSMBCopy"));
2060 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2065 pSMB->BufferFormat = 0x04;
2066 pSMB->Tid2 = target_tid;
2068 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2070 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2071 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2072 fromName, PATH_MAX, nls_codepage,
2074 name_len++; /* trailing null */
2076 pSMB->OldFileName[name_len] = 0x04; /* pad */
2077 /* protocol requires ASCII signature byte on Unicode string */
2078 pSMB->OldFileName[name_len + 1] = 0x00;
2080 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2081 toName, PATH_MAX, nls_codepage, remap);
2082 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2083 name_len2 *= 2; /* convert to bytes */
2084 } else { /* BB improve the check for buffer overruns BB */
2085 name_len = strnlen(fromName, PATH_MAX);
2086 name_len++; /* trailing null */
2087 strncpy(pSMB->OldFileName, fromName, name_len);
2088 name_len2 = strnlen(toName, PATH_MAX);
2089 name_len2++; /* trailing null */
2090 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2091 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2092 name_len2++; /* trailing null */
2093 name_len2++; /* signature byte */
2096 count = 1 /* 1st signature byte */ + name_len + name_len2;
2097 pSMB->hdr.smb_buf_length += count;
2098 pSMB->ByteCount = cpu_to_le16(count);
2100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2101 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2103 cFYI(1, ("Send error in copy = %d with %d files copied",
2104 rc, le16_to_cpu(pSMBr->CopyCount)));
2107 cifs_buf_release(pSMB);
2116 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2117 const char *fromName, const char *toName,
2118 const struct nls_table *nls_codepage)
2120 TRANSACTION2_SPI_REQ *pSMB = NULL;
2121 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2124 int name_len_target;
2126 int bytes_returned = 0;
2127 __u16 params, param_offset, offset, byte_count;
2129 cFYI(1, ("In Symlink Unix style"));
2131 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2136 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2138 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2139 /* find define for this maxpathcomponent */
2141 name_len++; /* trailing null */
2144 } else { /* BB improve the check for buffer overruns BB */
2145 name_len = strnlen(fromName, PATH_MAX);
2146 name_len++; /* trailing null */
2147 strncpy(pSMB->FileName, fromName, name_len);
2149 params = 6 + name_len;
2150 pSMB->MaxSetupCount = 0;
2154 pSMB->Reserved2 = 0;
2155 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2156 InformationLevel) - 4;
2157 offset = param_offset + params;
2159 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2160 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2162 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2163 /* find define for this maxpathcomponent */
2165 name_len_target++; /* trailing null */
2166 name_len_target *= 2;
2167 } else { /* BB improve the check for buffer overruns BB */
2168 name_len_target = strnlen(toName, PATH_MAX);
2169 name_len_target++; /* trailing null */
2170 strncpy(data_offset, toName, name_len_target);
2173 pSMB->MaxParameterCount = cpu_to_le16(2);
2174 /* BB find exact max on data count below from sess */
2175 pSMB->MaxDataCount = cpu_to_le16(1000);
2176 pSMB->SetupCount = 1;
2177 pSMB->Reserved3 = 0;
2178 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2179 byte_count = 3 /* pad */ + params + name_len_target;
2180 pSMB->DataCount = cpu_to_le16(name_len_target);
2181 pSMB->ParameterCount = cpu_to_le16(params);
2182 pSMB->TotalDataCount = pSMB->DataCount;
2183 pSMB->TotalParameterCount = pSMB->ParameterCount;
2184 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2185 pSMB->DataOffset = cpu_to_le16(offset);
2186 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2187 pSMB->Reserved4 = 0;
2188 pSMB->hdr.smb_buf_length += byte_count;
2189 pSMB->ByteCount = cpu_to_le16(byte_count);
2190 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2191 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2192 cifs_stats_inc(&tcon->num_symlinks);
2194 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2198 cifs_buf_release(pSMB);
2201 goto createSymLinkRetry;
2207 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2208 const char *fromName, const char *toName,
2209 const struct nls_table *nls_codepage, int remap)
2211 TRANSACTION2_SPI_REQ *pSMB = NULL;
2212 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2215 int name_len_target;
2217 int bytes_returned = 0;
2218 __u16 params, param_offset, offset, byte_count;
2220 cFYI(1, ("In Create Hard link Unix style"));
2221 createHardLinkRetry:
2222 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2227 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2228 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2229 PATH_MAX, nls_codepage, remap);
2230 name_len++; /* trailing null */
2233 } else { /* BB improve the check for buffer overruns BB */
2234 name_len = strnlen(toName, PATH_MAX);
2235 name_len++; /* trailing null */
2236 strncpy(pSMB->FileName, toName, name_len);
2238 params = 6 + name_len;
2239 pSMB->MaxSetupCount = 0;
2243 pSMB->Reserved2 = 0;
2244 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2245 InformationLevel) - 4;
2246 offset = param_offset + params;
2248 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2249 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2251 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2252 nls_codepage, remap);
2253 name_len_target++; /* trailing null */
2254 name_len_target *= 2;
2255 } else { /* BB improve the check for buffer overruns BB */
2256 name_len_target = strnlen(fromName, PATH_MAX);
2257 name_len_target++; /* trailing null */
2258 strncpy(data_offset, fromName, name_len_target);
2261 pSMB->MaxParameterCount = cpu_to_le16(2);
2262 /* BB find exact max on data count below from sess*/
2263 pSMB->MaxDataCount = cpu_to_le16(1000);
2264 pSMB->SetupCount = 1;
2265 pSMB->Reserved3 = 0;
2266 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2267 byte_count = 3 /* pad */ + params + name_len_target;
2268 pSMB->ParameterCount = cpu_to_le16(params);
2269 pSMB->TotalParameterCount = pSMB->ParameterCount;
2270 pSMB->DataCount = cpu_to_le16(name_len_target);
2271 pSMB->TotalDataCount = pSMB->DataCount;
2272 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2273 pSMB->DataOffset = cpu_to_le16(offset);
2274 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2275 pSMB->Reserved4 = 0;
2276 pSMB->hdr.smb_buf_length += byte_count;
2277 pSMB->ByteCount = cpu_to_le16(byte_count);
2278 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2279 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2280 cifs_stats_inc(&tcon->num_hardlinks);
2282 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2285 cifs_buf_release(pSMB);
2287 goto createHardLinkRetry;
2293 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2294 const char *fromName, const char *toName,
2295 const struct nls_table *nls_codepage, int remap)
2298 NT_RENAME_REQ *pSMB = NULL;
2299 RENAME_RSP *pSMBr = NULL;
2301 int name_len, name_len2;
2304 cFYI(1, ("In CIFSCreateHardLink"));
2305 winCreateHardLinkRetry:
2307 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2312 pSMB->SearchAttributes =
2313 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2315 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2316 pSMB->ClusterCount = 0;
2318 pSMB->BufferFormat = 0x04;
2320 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2322 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2323 PATH_MAX, nls_codepage, remap);
2324 name_len++; /* trailing null */
2326 pSMB->OldFileName[name_len] = 0; /* pad */
2327 pSMB->OldFileName[name_len + 1] = 0x04;
2329 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2330 toName, PATH_MAX, nls_codepage, remap);
2331 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2332 name_len2 *= 2; /* convert to bytes */
2333 } else { /* BB improve the check for buffer overruns BB */
2334 name_len = strnlen(fromName, PATH_MAX);
2335 name_len++; /* trailing null */
2336 strncpy(pSMB->OldFileName, fromName, name_len);
2337 name_len2 = strnlen(toName, PATH_MAX);
2338 name_len2++; /* trailing null */
2339 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2340 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2341 name_len2++; /* trailing null */
2342 name_len2++; /* signature byte */
2345 count = 1 /* string type byte */ + name_len + name_len2;
2346 pSMB->hdr.smb_buf_length += count;
2347 pSMB->ByteCount = cpu_to_le16(count);
2349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2350 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2351 cifs_stats_inc(&tcon->num_hardlinks);
2353 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2355 cifs_buf_release(pSMB);
2357 goto winCreateHardLinkRetry;
2363 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2364 const unsigned char *searchName,
2365 char *symlinkinfo, const int buflen,
2366 const struct nls_table *nls_codepage)
2368 /* SMB_QUERY_FILE_UNIX_LINK */
2369 TRANSACTION2_QPI_REQ *pSMB = NULL;
2370 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2374 __u16 params, byte_count;
2376 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2379 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2384 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2386 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2387 PATH_MAX, nls_codepage);
2388 name_len++; /* trailing null */
2390 } else { /* BB improve the check for buffer overruns BB */
2391 name_len = strnlen(searchName, PATH_MAX);
2392 name_len++; /* trailing null */
2393 strncpy(pSMB->FileName, searchName, name_len);
2396 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2397 pSMB->TotalDataCount = 0;
2398 pSMB->MaxParameterCount = cpu_to_le16(2);
2399 /* BB find exact max data count below from sess structure BB */
2400 pSMB->MaxDataCount = cpu_to_le16(4000);
2401 pSMB->MaxSetupCount = 0;
2405 pSMB->Reserved2 = 0;
2406 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2407 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2408 pSMB->DataCount = 0;
2409 pSMB->DataOffset = 0;
2410 pSMB->SetupCount = 1;
2411 pSMB->Reserved3 = 0;
2412 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2413 byte_count = params + 1 /* pad */ ;
2414 pSMB->TotalParameterCount = cpu_to_le16(params);
2415 pSMB->ParameterCount = pSMB->TotalParameterCount;
2416 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2417 pSMB->Reserved4 = 0;
2418 pSMB->hdr.smb_buf_length += byte_count;
2419 pSMB->ByteCount = cpu_to_le16(byte_count);
2421 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2422 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2424 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2426 /* decode response */
2428 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2429 if (rc || (pSMBr->ByteCount < 2))
2430 /* BB also check enough total bytes returned */
2431 rc = -EIO; /* bad smb */
2433 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2434 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2436 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2437 name_len = UniStrnlen((wchar_t *) ((char *)
2438 &pSMBr->hdr.Protocol + data_offset),
2439 min_t(const int, buflen, count) / 2);
2440 /* BB FIXME investigate remapping reserved chars here */
2441 cifs_strfromUCS_le(symlinkinfo,
2442 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2444 name_len, nls_codepage);
2446 strncpy(symlinkinfo,
2447 (char *) &pSMBr->hdr.Protocol +
2449 min_t(const int, buflen, count));
2451 symlinkinfo[buflen] = 0;
2452 /* just in case so calling code does not go off the end of buffer */
2455 cifs_buf_release(pSMB);
2457 goto querySymLinkRetry;
2461 /* Initialize NT TRANSACT SMB into small smb request buffer.
2462 This assumes that all NT TRANSACTS that we init here have
2463 total parm and data under about 400 bytes (to fit in small cifs
2464 buffer size), which is the case so far, it easily fits. NB:
2465 Setup words themselves and ByteCount
2466 MaxSetupCount (size of returned setup area) and
2467 MaxParameterCount (returned parms size) must be set by caller */
2469 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2470 const int parm_len, struct cifsTconInfo *tcon,
2475 struct smb_com_ntransact_req *pSMB;
2477 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2481 *ret_buf = (void *)pSMB;
2483 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2484 pSMB->TotalDataCount = 0;
2485 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2486 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2487 pSMB->ParameterCount = pSMB->TotalParameterCount;
2488 pSMB->DataCount = pSMB->TotalDataCount;
2489 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2490 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2491 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2492 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2493 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2494 pSMB->SubCommand = cpu_to_le16(sub_command);
2499 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2500 int *pdatalen, int *pparmlen)
2503 __u32 data_count, data_offset, parm_count, parm_offset;
2504 struct smb_com_ntransact_rsp *pSMBr;
2509 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2511 /* ByteCount was converted from little endian in SendReceive */
2512 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2513 (char *)&pSMBr->ByteCount;
2515 data_offset = le32_to_cpu(pSMBr->DataOffset);
2516 data_count = le32_to_cpu(pSMBr->DataCount);
2517 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2518 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2520 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2521 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2523 /* should we also check that parm and data areas do not overlap? */
2524 if (*ppparm > end_of_smb) {
2525 cFYI(1, ("parms start after end of smb"));
2527 } else if (parm_count + *ppparm > end_of_smb) {
2528 cFYI(1, ("parm end after end of smb"));
2530 } else if (*ppdata > end_of_smb) {
2531 cFYI(1, ("data starts after end of smb"));
2533 } else if (data_count + *ppdata > end_of_smb) {
2534 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2535 *ppdata, data_count, (data_count + *ppdata),
2536 end_of_smb, pSMBr));
2538 } else if (parm_count + data_count > pSMBr->ByteCount) {
2539 cFYI(1, ("parm count and data count larger than SMB"));
2546 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2547 const unsigned char *searchName,
2548 char *symlinkinfo, const int buflen, __u16 fid,
2549 const struct nls_table *nls_codepage)
2554 struct smb_com_transaction_ioctl_req *pSMB;
2555 struct smb_com_transaction_ioctl_rsp *pSMBr;
2557 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2558 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2563 pSMB->TotalParameterCount = 0 ;
2564 pSMB->TotalDataCount = 0;
2565 pSMB->MaxParameterCount = cpu_to_le32(2);
2566 /* BB find exact data count max from sess structure BB */
2567 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2568 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2569 pSMB->MaxSetupCount = 4;
2571 pSMB->ParameterOffset = 0;
2572 pSMB->DataCount = 0;
2573 pSMB->DataOffset = 0;
2574 pSMB->SetupCount = 4;
2575 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2576 pSMB->ParameterCount = pSMB->TotalParameterCount;
2577 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2578 pSMB->IsFsctl = 1; /* FSCTL */
2579 pSMB->IsRootFlag = 0;
2580 pSMB->Fid = fid; /* file handle always le */
2581 pSMB->ByteCount = 0;
2583 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2584 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2586 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2587 } else { /* decode response */
2588 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2589 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2590 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2591 /* BB also check enough total bytes returned */
2592 rc = -EIO; /* bad smb */
2594 if (data_count && (data_count < 2048)) {
2595 char *end_of_smb = 2 /* sizeof byte count */ +
2597 (char *)&pSMBr->ByteCount;
2599 struct reparse_data *reparse_buf =
2600 (struct reparse_data *)
2601 ((char *)&pSMBr->hdr.Protocol
2603 if ((char *)reparse_buf >= end_of_smb) {
2607 if ((reparse_buf->LinkNamesBuf +
2608 reparse_buf->TargetNameOffset +
2609 reparse_buf->TargetNameLen) >
2611 cFYI(1,("reparse buf extended beyond SMB"));
2616 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2617 name_len = UniStrnlen((wchar_t *)
2618 (reparse_buf->LinkNamesBuf +
2619 reparse_buf->TargetNameOffset),
2621 reparse_buf->TargetNameLen / 2));
2622 cifs_strfromUCS_le(symlinkinfo,
2623 (__le16 *) (reparse_buf->LinkNamesBuf +
2624 reparse_buf->TargetNameOffset),
2625 name_len, nls_codepage);
2626 } else { /* ASCII names */
2627 strncpy(symlinkinfo,
2628 reparse_buf->LinkNamesBuf +
2629 reparse_buf->TargetNameOffset,
2630 min_t(const int, buflen,
2631 reparse_buf->TargetNameLen));
2635 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2637 symlinkinfo[buflen] = 0; /* just in case so the caller
2638 does not go off the end of the buffer */
2639 cFYI(1, ("readlink result - %s", symlinkinfo));
2643 cifs_buf_release(pSMB);
2645 /* Note: On -EAGAIN error only caller can retry on handle based calls
2646 since file handle passed in no longer valid */
2651 #ifdef CONFIG_CIFS_POSIX
2653 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2654 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2655 struct cifs_posix_ace *cifs_ace)
2657 /* u8 cifs fields do not need le conversion */
2658 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2659 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2660 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2661 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2666 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2667 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2668 const int acl_type, const int size_of_data_area)
2673 struct cifs_posix_ace *pACE;
2674 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2675 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2677 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2680 if (acl_type & ACL_TYPE_ACCESS) {
2681 count = le16_to_cpu(cifs_acl->access_entry_count);
2682 pACE = &cifs_acl->ace_array[0];
2683 size = sizeof(struct cifs_posix_acl);
2684 size += sizeof(struct cifs_posix_ace) * count;
2685 /* check if we would go beyond end of SMB */
2686 if (size_of_data_area < size) {
2687 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2688 size_of_data_area, size));
2691 } else if (acl_type & ACL_TYPE_DEFAULT) {
2692 count = le16_to_cpu(cifs_acl->access_entry_count);
2693 size = sizeof(struct cifs_posix_acl);
2694 size += sizeof(struct cifs_posix_ace) * count;
2695 /* skip past access ACEs to get to default ACEs */
2696 pACE = &cifs_acl->ace_array[count];
2697 count = le16_to_cpu(cifs_acl->default_entry_count);
2698 size += sizeof(struct cifs_posix_ace) * count;
2699 /* check if we would go beyond end of SMB */
2700 if (size_of_data_area < size)
2707 size = posix_acl_xattr_size(count);
2708 if ((buflen == 0) || (local_acl == NULL)) {
2709 /* used to query ACL EA size */
2710 } else if (size > buflen) {
2712 } else /* buffer big enough */ {
2713 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2714 for (i = 0; i < count ; i++) {
2715 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2722 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2723 const posix_acl_xattr_entry *local_ace)
2725 __u16 rc = 0; /* 0 = ACL converted ok */
2727 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2728 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2729 /* BB is there a better way to handle the large uid? */
2730 if (local_ace->e_id == cpu_to_le32(-1)) {
2731 /* Probably no need to le convert -1 on any arch but can not hurt */
2732 cifs_ace->cifs_uid = cpu_to_le64(-1);
2734 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2735 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2739 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2740 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2741 const int buflen, const int acl_type)
2744 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2745 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2749 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2752 count = posix_acl_xattr_count((size_t)buflen);
2753 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2754 count, buflen, le32_to_cpu(local_acl->a_version)));
2755 if (le32_to_cpu(local_acl->a_version) != 2) {
2756 cFYI(1, ("unknown POSIX ACL version %d",
2757 le32_to_cpu(local_acl->a_version)));
2760 cifs_acl->version = cpu_to_le16(1);
2761 if (acl_type == ACL_TYPE_ACCESS)
2762 cifs_acl->access_entry_count = cpu_to_le16(count);
2763 else if (acl_type == ACL_TYPE_DEFAULT)
2764 cifs_acl->default_entry_count = cpu_to_le16(count);
2766 cFYI(1, ("unknown ACL type %d", acl_type));
2769 for (i = 0; i < count; i++) {
2770 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2771 &local_acl->a_entries[i]);
2773 /* ACE not converted */
2778 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2779 rc += sizeof(struct cifs_posix_acl);
2780 /* BB add check to make sure ACL does not overflow SMB */
2786 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2787 const unsigned char *searchName,
2788 char *acl_inf, const int buflen, const int acl_type,
2789 const struct nls_table *nls_codepage, int remap)
2791 /* SMB_QUERY_POSIX_ACL */
2792 TRANSACTION2_QPI_REQ *pSMB = NULL;
2793 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2797 __u16 params, byte_count;
2799 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2802 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2807 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2809 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2810 PATH_MAX, nls_codepage, remap);
2811 name_len++; /* trailing null */
2813 pSMB->FileName[name_len] = 0;
2814 pSMB->FileName[name_len+1] = 0;
2815 } else { /* BB improve the check for buffer overruns BB */
2816 name_len = strnlen(searchName, PATH_MAX);
2817 name_len++; /* trailing null */
2818 strncpy(pSMB->FileName, searchName, name_len);
2821 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2822 pSMB->TotalDataCount = 0;
2823 pSMB->MaxParameterCount = cpu_to_le16(2);
2824 /* BB find exact max data count below from sess structure BB */
2825 pSMB->MaxDataCount = cpu_to_le16(4000);
2826 pSMB->MaxSetupCount = 0;
2830 pSMB->Reserved2 = 0;
2831 pSMB->ParameterOffset = cpu_to_le16(
2832 offsetof(struct smb_com_transaction2_qpi_req,
2833 InformationLevel) - 4);
2834 pSMB->DataCount = 0;
2835 pSMB->DataOffset = 0;
2836 pSMB->SetupCount = 1;
2837 pSMB->Reserved3 = 0;
2838 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2839 byte_count = params + 1 /* pad */ ;
2840 pSMB->TotalParameterCount = cpu_to_le16(params);
2841 pSMB->ParameterCount = pSMB->TotalParameterCount;
2842 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2843 pSMB->Reserved4 = 0;
2844 pSMB->hdr.smb_buf_length += byte_count;
2845 pSMB->ByteCount = cpu_to_le16(byte_count);
2847 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2848 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2849 cifs_stats_inc(&tcon->num_acl_get);
2851 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2853 /* decode response */
2855 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2856 if (rc || (pSMBr->ByteCount < 2))
2857 /* BB also check enough total bytes returned */
2858 rc = -EIO; /* bad smb */
2860 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2861 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2862 rc = cifs_copy_posix_acl(acl_inf,
2863 (char *)&pSMBr->hdr.Protocol+data_offset,
2864 buflen, acl_type, count);
2867 cifs_buf_release(pSMB);
2874 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2875 const unsigned char *fileName,
2876 const char *local_acl, const int buflen,
2878 const struct nls_table *nls_codepage, int remap)
2880 struct smb_com_transaction2_spi_req *pSMB = NULL;
2881 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2885 int bytes_returned = 0;
2886 __u16 params, byte_count, data_count, param_offset, offset;
2888 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2890 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2894 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2896 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2897 PATH_MAX, nls_codepage, remap);
2898 name_len++; /* trailing null */
2900 } else { /* BB improve the check for buffer overruns BB */
2901 name_len = strnlen(fileName, PATH_MAX);
2902 name_len++; /* trailing null */
2903 strncpy(pSMB->FileName, fileName, name_len);
2905 params = 6 + name_len;
2906 pSMB->MaxParameterCount = cpu_to_le16(2);
2907 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2908 pSMB->MaxSetupCount = 0;
2912 pSMB->Reserved2 = 0;
2913 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2914 InformationLevel) - 4;
2915 offset = param_offset + params;
2916 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2917 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2919 /* convert to on the wire format for POSIX ACL */
2920 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2922 if (data_count == 0) {
2924 goto setACLerrorExit;
2926 pSMB->DataOffset = cpu_to_le16(offset);
2927 pSMB->SetupCount = 1;
2928 pSMB->Reserved3 = 0;
2929 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2930 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2931 byte_count = 3 /* pad */ + params + data_count;
2932 pSMB->DataCount = cpu_to_le16(data_count);
2933 pSMB->TotalDataCount = pSMB->DataCount;
2934 pSMB->ParameterCount = cpu_to_le16(params);
2935 pSMB->TotalParameterCount = pSMB->ParameterCount;
2936 pSMB->Reserved4 = 0;
2937 pSMB->hdr.smb_buf_length += byte_count;
2938 pSMB->ByteCount = cpu_to_le16(byte_count);
2939 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2940 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2942 cFYI(1, ("Set POSIX ACL returned %d", rc));
2946 cifs_buf_release(pSMB);
2952 /* BB fix tabs in this function FIXME BB */
2954 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2955 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2958 struct smb_t2_qfi_req *pSMB = NULL;
2959 struct smb_t2_qfi_rsp *pSMBr = NULL;
2961 __u16 params, byte_count;
2963 cFYI(1, ("In GetExtAttr"));
2968 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2973 params = 2 /* level */ +2 /* fid */;
2974 pSMB->t2.TotalDataCount = 0;
2975 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2976 /* BB find exact max data count below from sess structure BB */
2977 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2978 pSMB->t2.MaxSetupCount = 0;
2979 pSMB->t2.Reserved = 0;
2981 pSMB->t2.Timeout = 0;
2982 pSMB->t2.Reserved2 = 0;
2983 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2985 pSMB->t2.DataCount = 0;
2986 pSMB->t2.DataOffset = 0;
2987 pSMB->t2.SetupCount = 1;
2988 pSMB->t2.Reserved3 = 0;
2989 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2990 byte_count = params + 1 /* pad */ ;
2991 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2992 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2993 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2996 pSMB->hdr.smb_buf_length += byte_count;
2997 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2999 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3000 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3002 cFYI(1, ("error %d in GetExtAttr", rc));
3004 /* decode response */
3005 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3006 if (rc || (pSMBr->ByteCount < 2))
3007 /* BB also check enough total bytes returned */
3008 /* If rc should we check for EOPNOSUPP and
3009 disable the srvino flag? or in caller? */
3010 rc = -EIO; /* bad smb */
3012 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3013 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3014 struct file_chattr_info *pfinfo;
3015 /* BB Do we need a cast or hash here ? */
3017 cFYI(1, ("Illegal size ret in GetExtAttr"));
3021 pfinfo = (struct file_chattr_info *)
3022 (data_offset + (char *) &pSMBr->hdr.Protocol);
3023 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3024 *pMask = le64_to_cpu(pfinfo->mask);
3028 cifs_buf_release(pSMB);
3030 goto GetExtAttrRetry;
3034 #endif /* CONFIG_POSIX */
3037 /* security id for everyone */
3038 static const struct cifs_sid sid_everyone =
3039 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
3041 static const struct cifs_sid sid_user =
3042 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
3044 /* Convert CIFS ACL to POSIX form */
3045 static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
3050 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3052 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3053 /* BB fix up return info */ char *acl_inf, const int buflen,
3054 const int acl_type /* ACCESS/DEFAULT not sure implication */)
3058 QUERY_SEC_DESC_REQ * pSMB;
3061 cFYI(1, ("GetCifsACL"));
3063 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3064 8 /* parm len */, tcon, (void **) &pSMB);
3068 pSMB->MaxParameterCount = cpu_to_le32(4);
3069 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3070 pSMB->MaxSetupCount = 0;
3071 pSMB->Fid = fid; /* file handle always le */
3072 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3074 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3075 pSMB->hdr.smb_buf_length += 11;
3076 iov[0].iov_base = (char *)pSMB;
3077 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3079 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3080 cifs_stats_inc(&tcon->num_acl_get);
3082 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3083 } else { /* decode response */
3084 struct cifs_sid *psec_desc;
3089 struct smb_com_ntransact_rsp *pSMBr;
3091 /* validate_nttransact */
3092 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3093 (char **)&psec_desc,
3094 &parm_len, &data_len);
3097 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3099 cERROR(1, ("smb %p parm %p data %p",
3100 pSMBr, parm, psec_desc)); /* BB removeme BB */
3102 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3103 rc = -EIO; /* bad smb */
3107 /* BB check that data area is minimum length and as big as acl_len */
3109 acl_len = le32_to_cpu(*(__le32 *)parm);
3110 /* BB check if (acl_len > bufsize) */
3112 parse_sec_desc(psec_desc, acl_len);
3115 if (buf_type == CIFS_SMALL_BUFFER)
3116 cifs_small_buf_release(iov[0].iov_base);
3117 else if (buf_type == CIFS_LARGE_BUFFER)
3118 cifs_buf_release(iov[0].iov_base);
3119 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3123 /* Legacy Query Path Information call for lookup to old servers such
3125 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3126 const unsigned char *searchName,
3127 FILE_ALL_INFO *pFinfo,
3128 const struct nls_table *nls_codepage, int remap)
3130 QUERY_INFORMATION_REQ * pSMB;
3131 QUERY_INFORMATION_RSP * pSMBr;
3136 cFYI(1, ("In SMBQPath path %s", searchName));
3138 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3143 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3145 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3146 PATH_MAX, nls_codepage, remap);
3147 name_len++; /* trailing null */
3150 name_len = strnlen(searchName, PATH_MAX);
3151 name_len++; /* trailing null */
3152 strncpy(pSMB->FileName, searchName, name_len);
3154 pSMB->BufferFormat = 0x04;
3155 name_len++; /* account for buffer type byte */
3156 pSMB->hdr.smb_buf_length += (__u16) name_len;
3157 pSMB->ByteCount = cpu_to_le16(name_len);
3159 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3160 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3162 cFYI(1, ("Send error in QueryInfo = %d", rc));
3163 } else if (pFinfo) { /* decode response */
3165 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3166 /* BB FIXME - add time zone adjustment BB */
3167 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3170 /* decode time fields */
3171 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3172 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3173 pFinfo->LastAccessTime = 0;
3174 pFinfo->AllocationSize =
3175 cpu_to_le64(le32_to_cpu(pSMBr->size));
3176 pFinfo->EndOfFile = pFinfo->AllocationSize;
3177 pFinfo->Attributes =
3178 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3180 rc = -EIO; /* bad buffer passed in */
3182 cifs_buf_release(pSMB);
3194 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3195 const unsigned char *searchName,
3196 FILE_ALL_INFO * pFindData,
3197 int legacy /* old style infolevel */,
3198 const struct nls_table *nls_codepage, int remap)
3200 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3201 TRANSACTION2_QPI_REQ *pSMB = NULL;
3202 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3206 __u16 params, byte_count;
3208 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3210 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3215 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3217 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3218 PATH_MAX, nls_codepage, remap);
3219 name_len++; /* trailing null */
3221 } else { /* BB improve the check for buffer overruns BB */
3222 name_len = strnlen(searchName, PATH_MAX);
3223 name_len++; /* trailing null */
3224 strncpy(pSMB->FileName, searchName, name_len);
3227 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3228 pSMB->TotalDataCount = 0;
3229 pSMB->MaxParameterCount = cpu_to_le16(2);
3230 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3231 pSMB->MaxSetupCount = 0;
3235 pSMB->Reserved2 = 0;
3236 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3237 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3238 pSMB->DataCount = 0;
3239 pSMB->DataOffset = 0;
3240 pSMB->SetupCount = 1;
3241 pSMB->Reserved3 = 0;
3242 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3243 byte_count = params + 1 /* pad */ ;
3244 pSMB->TotalParameterCount = cpu_to_le16(params);
3245 pSMB->ParameterCount = pSMB->TotalParameterCount;
3247 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3249 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3250 pSMB->Reserved4 = 0;
3251 pSMB->hdr.smb_buf_length += byte_count;
3252 pSMB->ByteCount = cpu_to_le16(byte_count);
3254 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3255 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3257 cFYI(1, ("Send error in QPathInfo = %d", rc));
3258 } else { /* decode response */
3259 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3261 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3263 else if (!legacy && (pSMBr->ByteCount < 40))
3264 rc = -EIO; /* bad smb */
3265 else if (legacy && (pSMBr->ByteCount < 24))
3266 rc = -EIO; /* 24 or 26 expected but we do not read
3268 else if (pFindData) {
3270 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3271 if (legacy) /* we do not read the last field, EAsize,
3272 fortunately since it varies by subdialect
3273 and on Set vs. Get, is two bytes or 4
3274 bytes depending but we don't care here */
3275 size = sizeof(FILE_INFO_STANDARD);
3277 size = sizeof(FILE_ALL_INFO);
3278 memcpy((char *) pFindData,
3279 (char *) &pSMBr->hdr.Protocol +
3284 cifs_buf_release(pSMB);
3286 goto QPathInfoRetry;
3292 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3293 const unsigned char *searchName,
3294 FILE_UNIX_BASIC_INFO * pFindData,
3295 const struct nls_table *nls_codepage, int remap)
3297 /* SMB_QUERY_FILE_UNIX_BASIC */
3298 TRANSACTION2_QPI_REQ *pSMB = NULL;
3299 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3301 int bytes_returned = 0;
3303 __u16 params, byte_count;
3305 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3307 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3312 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3314 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3315 PATH_MAX, nls_codepage, remap);
3316 name_len++; /* trailing null */
3318 } else { /* BB improve the check for buffer overruns BB */
3319 name_len = strnlen(searchName, PATH_MAX);
3320 name_len++; /* trailing null */
3321 strncpy(pSMB->FileName, searchName, name_len);
3324 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3325 pSMB->TotalDataCount = 0;
3326 pSMB->MaxParameterCount = cpu_to_le16(2);
3327 /* BB find exact max SMB PDU from sess structure BB */
3328 pSMB->MaxDataCount = cpu_to_le16(4000);
3329 pSMB->MaxSetupCount = 0;
3333 pSMB->Reserved2 = 0;
3334 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3335 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3336 pSMB->DataCount = 0;
3337 pSMB->DataOffset = 0;
3338 pSMB->SetupCount = 1;
3339 pSMB->Reserved3 = 0;
3340 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3341 byte_count = params + 1 /* pad */ ;
3342 pSMB->TotalParameterCount = cpu_to_le16(params);
3343 pSMB->ParameterCount = pSMB->TotalParameterCount;
3344 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3345 pSMB->Reserved4 = 0;
3346 pSMB->hdr.smb_buf_length += byte_count;
3347 pSMB->ByteCount = cpu_to_le16(byte_count);
3349 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3350 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3352 cFYI(1, ("Send error in QPathInfo = %d", rc));
3353 } else { /* decode response */
3354 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3356 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3357 rc = -EIO; /* bad smb */
3359 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3360 memcpy((char *) pFindData,
3361 (char *) &pSMBr->hdr.Protocol +
3363 sizeof (FILE_UNIX_BASIC_INFO));
3366 cifs_buf_release(pSMB);
3368 goto UnixQPathInfoRetry;
3373 #if 0 /* function unused at present */
3374 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3375 const char *searchName, FILE_ALL_INFO * findData,
3376 const struct nls_table *nls_codepage)
3378 /* level 257 SMB_ */
3379 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3380 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3384 __u16 params, byte_count;
3386 cFYI(1, ("In FindUnique"));
3388 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3393 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3395 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3396 PATH_MAX, nls_codepage);
3397 name_len++; /* trailing null */
3399 } else { /* BB improve the check for buffer overruns BB */
3400 name_len = strnlen(searchName, PATH_MAX);
3401 name_len++; /* trailing null */
3402 strncpy(pSMB->FileName, searchName, name_len);
3405 params = 12 + name_len /* includes null */ ;
3406 pSMB->TotalDataCount = 0; /* no EAs */
3407 pSMB->MaxParameterCount = cpu_to_le16(2);
3408 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3409 pSMB->MaxSetupCount = 0;
3413 pSMB->Reserved2 = 0;
3414 pSMB->ParameterOffset = cpu_to_le16(
3415 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3416 pSMB->DataCount = 0;
3417 pSMB->DataOffset = 0;
3418 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3419 pSMB->Reserved3 = 0;
3420 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3421 byte_count = params + 1 /* pad */ ;
3422 pSMB->TotalParameterCount = cpu_to_le16(params);
3423 pSMB->ParameterCount = pSMB->TotalParameterCount;
3424 pSMB->SearchAttributes =
3425 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3427 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3428 pSMB->SearchFlags = cpu_to_le16(1);
3429 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3430 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3431 pSMB->hdr.smb_buf_length += byte_count;
3432 pSMB->ByteCount = cpu_to_le16(byte_count);
3434 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3438 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3439 } else { /* decode response */
3440 cifs_stats_inc(&tcon->num_ffirst);
3444 cifs_buf_release(pSMB);
3446 goto findUniqueRetry;
3450 #endif /* end unused (temporarily) function */
3452 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3454 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3455 const char *searchName,
3456 const struct nls_table *nls_codepage,
3458 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3460 /* level 257 SMB_ */
3461 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3462 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3463 T2_FFIRST_RSP_PARMS * parms;
3465 int bytes_returned = 0;
3467 __u16 params, byte_count;
3469 cFYI(1, ("In FindFirst for %s", searchName));
3472 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3477 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3479 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3480 PATH_MAX, nls_codepage, remap);
3481 /* We can not add the asterik earlier in case
3482 it got remapped to 0xF03A as if it were part of the
3483 directory name instead of a wildcard */
3485 pSMB->FileName[name_len] = dirsep;
3486 pSMB->FileName[name_len+1] = 0;
3487 pSMB->FileName[name_len+2] = '*';
3488 pSMB->FileName[name_len+3] = 0;
3489 name_len += 4; /* now the trailing null */
3490 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3491 pSMB->FileName[name_len+1] = 0;
3493 } else { /* BB add check for overrun of SMB buf BB */
3494 name_len = strnlen(searchName, PATH_MAX);
3495 /* BB fix here and in unicode clause above ie
3496 if (name_len > buffersize-header)
3497 free buffer exit; BB */
3498 strncpy(pSMB->FileName, searchName, name_len);
3499 pSMB->FileName[name_len] = dirsep;
3500 pSMB->FileName[name_len+1] = '*';
3501 pSMB->FileName[name_len+2] = 0;
3505 params = 12 + name_len /* includes null */ ;
3506 pSMB->TotalDataCount = 0; /* no EAs */
3507 pSMB->MaxParameterCount = cpu_to_le16(10);
3508 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3509 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3510 pSMB->MaxSetupCount = 0;
3514 pSMB->Reserved2 = 0;
3515 byte_count = params + 1 /* pad */ ;
3516 pSMB->TotalParameterCount = cpu_to_le16(params);
3517 pSMB->ParameterCount = pSMB->TotalParameterCount;
3518 pSMB->ParameterOffset = cpu_to_le16(
3519 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3521 pSMB->DataCount = 0;
3522 pSMB->DataOffset = 0;
3523 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3524 pSMB->Reserved3 = 0;
3525 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3526 pSMB->SearchAttributes =
3527 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3529 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3530 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3531 CIFS_SEARCH_RETURN_RESUME);
3532 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3534 /* BB what should we set StorageType to? Does it matter? BB */
3535 pSMB->SearchStorageType = 0;
3536 pSMB->hdr.smb_buf_length += byte_count;
3537 pSMB->ByteCount = cpu_to_le16(byte_count);
3539 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3540 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3541 cifs_stats_inc(&tcon->num_ffirst);
3543 if (rc) {/* BB add logic to retry regular search if Unix search
3544 rejected unexpectedly by server */
3545 /* BB Add code to handle unsupported level rc */
3546 cFYI(1, ("Error in FindFirst = %d", rc));
3548 cifs_buf_release(pSMB);
3550 /* BB eventually could optimize out free and realloc of buf */
3553 goto findFirstRetry;
3554 } else { /* decode response */
3555 /* BB remember to free buffer if error BB */
3556 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3558 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3559 psrch_inf->unicode = TRUE;
3561 psrch_inf->unicode = FALSE;
3563 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3564 psrch_inf->smallBuf = 0;
3565 psrch_inf->srch_entries_start =
3566 (char *) &pSMBr->hdr.Protocol +
3567 le16_to_cpu(pSMBr->t2.DataOffset);
3568 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3569 le16_to_cpu(pSMBr->t2.ParameterOffset));
3571 if (parms->EndofSearch)
3572 psrch_inf->endOfSearch = TRUE;
3574 psrch_inf->endOfSearch = FALSE;
3576 psrch_inf->entries_in_buffer =
3577 le16_to_cpu(parms->SearchCount);
3578 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3579 psrch_inf->entries_in_buffer;
3580 *pnetfid = parms->SearchHandle;
3582 cifs_buf_release(pSMB);
3589 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3590 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3592 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3593 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3594 T2_FNEXT_RSP_PARMS * parms;
3595 char *response_data;
3597 int bytes_returned, name_len;
3598 __u16 params, byte_count;
3600 cFYI(1, ("In FindNext"));
3602 if (psrch_inf->endOfSearch == TRUE)
3605 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3610 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3612 pSMB->TotalDataCount = 0; /* no EAs */
3613 pSMB->MaxParameterCount = cpu_to_le16(8);
3614 pSMB->MaxDataCount =
3615 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3617 pSMB->MaxSetupCount = 0;
3621 pSMB->Reserved2 = 0;
3622 pSMB->ParameterOffset = cpu_to_le16(
3623 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3624 pSMB->DataCount = 0;
3625 pSMB->DataOffset = 0;
3626 pSMB->SetupCount = 1;
3627 pSMB->Reserved3 = 0;
3628 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3629 pSMB->SearchHandle = searchHandle; /* always kept as le */
3631 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3632 /* test for Unix extensions */
3633 /* if (tcon->ses->capabilities & CAP_UNIX) {
3634 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3635 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3637 pSMB->InformationLevel =
3638 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3639 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3641 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3642 pSMB->ResumeKey = psrch_inf->resume_key;
3644 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3646 name_len = psrch_inf->resume_name_len;
3648 if (name_len < PATH_MAX) {
3649 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3650 byte_count += name_len;
3651 /* 14 byte parm len above enough for 2 byte null terminator */
3652 pSMB->ResumeFileName[name_len] = 0;
3653 pSMB->ResumeFileName[name_len+1] = 0;
3656 goto FNext2_err_exit;
3658 byte_count = params + 1 /* pad */ ;
3659 pSMB->TotalParameterCount = cpu_to_le16(params);
3660 pSMB->ParameterCount = pSMB->TotalParameterCount;
3661 pSMB->hdr.smb_buf_length += byte_count;
3662 pSMB->ByteCount = cpu_to_le16(byte_count);
3664 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3665 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3666 cifs_stats_inc(&tcon->num_fnext);
3669 psrch_inf->endOfSearch = TRUE;
3670 rc = 0; /* search probably was closed at end of search*/
3672 cFYI(1, ("FindNext returned = %d", rc));
3673 } else { /* decode response */
3674 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3677 /* BB fixme add lock for file (srch_info) struct here */
3678 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3679 psrch_inf->unicode = TRUE;
3681 psrch_inf->unicode = FALSE;
3682 response_data = (char *) &pSMBr->hdr.Protocol +
3683 le16_to_cpu(pSMBr->t2.ParameterOffset);
3684 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3685 response_data = (char *)&pSMBr->hdr.Protocol +
3686 le16_to_cpu(pSMBr->t2.DataOffset);
3687 if (psrch_inf->smallBuf)
3688 cifs_small_buf_release(
3689 psrch_inf->ntwrk_buf_start);
3691 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3692 psrch_inf->srch_entries_start = response_data;
3693 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3694 psrch_inf->smallBuf = 0;
3695 if (parms->EndofSearch)
3696 psrch_inf->endOfSearch = TRUE;
3698 psrch_inf->endOfSearch = FALSE;
3699 psrch_inf->entries_in_buffer =
3700 le16_to_cpu(parms->SearchCount);
3701 psrch_inf->index_of_last_entry +=
3702 psrch_inf->entries_in_buffer;
3703 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3704 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3706 /* BB fixme add unlock here */
3711 /* BB On error, should we leave previous search buf (and count and
3712 last entry fields) intact or free the previous one? */
3714 /* Note: On -EAGAIN error only caller can retry on handle based calls
3715 since file handle passed in no longer valid */
3718 cifs_buf_release(pSMB);
3723 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3724 const __u16 searchHandle)
3727 FINDCLOSE_REQ *pSMB = NULL;
3728 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3731 cFYI(1, ("In CIFSSMBFindClose"));
3732 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3734 /* no sense returning error if session restarted
3735 as file handle has been closed */
3741 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3742 pSMB->FileID = searchHandle;
3743 pSMB->ByteCount = 0;
3744 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3745 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3747 cERROR(1, ("Send error in FindClose = %d", rc));
3749 cifs_stats_inc(&tcon->num_fclose);
3750 cifs_small_buf_release(pSMB);
3752 /* Since session is dead, search handle closed on server already */
3760 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3761 const unsigned char *searchName,
3762 __u64 * inode_number,
3763 const struct nls_table *nls_codepage, int remap)
3766 TRANSACTION2_QPI_REQ *pSMB = NULL;
3767 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3768 int name_len, bytes_returned;
3769 __u16 params, byte_count;
3771 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3775 GetInodeNumberRetry:
3776 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3781 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3783 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3784 PATH_MAX, nls_codepage, remap);
3785 name_len++; /* trailing null */
3787 } else { /* BB improve the check for buffer overruns BB */
3788 name_len = strnlen(searchName, PATH_MAX);
3789 name_len++; /* trailing null */
3790 strncpy(pSMB->FileName, searchName, name_len);
3793 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3794 pSMB->TotalDataCount = 0;
3795 pSMB->MaxParameterCount = cpu_to_le16(2);
3796 /* BB find exact max data count below from sess structure BB */
3797 pSMB->MaxDataCount = cpu_to_le16(4000);
3798 pSMB->MaxSetupCount = 0;
3802 pSMB->Reserved2 = 0;
3803 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3804 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3805 pSMB->DataCount = 0;
3806 pSMB->DataOffset = 0;
3807 pSMB->SetupCount = 1;
3808 pSMB->Reserved3 = 0;
3809 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3810 byte_count = params + 1 /* pad */ ;
3811 pSMB->TotalParameterCount = cpu_to_le16(params);
3812 pSMB->ParameterCount = pSMB->TotalParameterCount;
3813 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3814 pSMB->Reserved4 = 0;
3815 pSMB->hdr.smb_buf_length += byte_count;
3816 pSMB->ByteCount = cpu_to_le16(byte_count);
3818 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3819 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3821 cFYI(1, ("error %d in QueryInternalInfo", rc));
3823 /* decode response */
3824 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3825 if (rc || (pSMBr->ByteCount < 2))
3826 /* BB also check enough total bytes returned */
3827 /* If rc should we check for EOPNOSUPP and
3828 disable the srvino flag? or in caller? */
3829 rc = -EIO; /* bad smb */
3831 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3832 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3833 struct file_internal_info *pfinfo;
3834 /* BB Do we need a cast or hash here ? */
3836 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3838 goto GetInodeNumOut;
3840 pfinfo = (struct file_internal_info *)
3841 (data_offset + (char *) &pSMBr->hdr.Protocol);
3842 *inode_number = pfinfo->UniqueId;
3846 cifs_buf_release(pSMB);
3848 goto GetInodeNumberRetry;
3853 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3854 const unsigned char *searchName,
3855 unsigned char **targetUNCs,
3856 unsigned int *number_of_UNC_in_array,
3857 const struct nls_table *nls_codepage, int remap)
3859 /* TRANS2_GET_DFS_REFERRAL */
3860 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3861 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3862 struct dfs_referral_level_3 *referrals = NULL;
3868 __u16 params, byte_count;
3869 *number_of_UNC_in_array = 0;
3872 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3876 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3881 /* server pointer checked in called function,
3882 but should never be null here anyway */
3883 pSMB->hdr.Mid = GetNextMid(ses->server);
3884 pSMB->hdr.Tid = ses->ipc_tid;
3885 pSMB->hdr.Uid = ses->Suid;
3886 if (ses->capabilities & CAP_STATUS32) {
3887 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3889 if (ses->capabilities & CAP_DFS) {
3890 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3893 if (ses->capabilities & CAP_UNICODE) {
3894 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3896 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3897 searchName, PATH_MAX, nls_codepage, remap);
3898 name_len++; /* trailing null */
3900 } else { /* BB improve the check for buffer overruns BB */
3901 name_len = strnlen(searchName, PATH_MAX);
3902 name_len++; /* trailing null */
3903 strncpy(pSMB->RequestFileName, searchName, name_len);
3907 if (ses->server->secMode &
3908 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3909 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3912 pSMB->hdr.Uid = ses->Suid;
3914 params = 2 /* level */ + name_len /*includes null */ ;
3915 pSMB->TotalDataCount = 0;
3916 pSMB->DataCount = 0;
3917 pSMB->DataOffset = 0;
3918 pSMB->MaxParameterCount = 0;
3919 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3920 pSMB->MaxSetupCount = 0;
3924 pSMB->Reserved2 = 0;
3925 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3926 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3927 pSMB->SetupCount = 1;
3928 pSMB->Reserved3 = 0;
3929 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3930 byte_count = params + 3 /* pad */ ;
3931 pSMB->ParameterCount = cpu_to_le16(params);
3932 pSMB->TotalParameterCount = pSMB->ParameterCount;
3933 pSMB->MaxReferralLevel = cpu_to_le16(3);
3934 pSMB->hdr.smb_buf_length += byte_count;
3935 pSMB->ByteCount = cpu_to_le16(byte_count);
3937 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3940 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3941 } else { /* decode response */
3942 /* BB Add logic to parse referrals here */
3943 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3945 /* BB Also check if enough total bytes returned? */
3946 if (rc || (pSMBr->ByteCount < 17))
3947 rc = -EIO; /* bad smb */
3949 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3950 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3953 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3954 pSMBr->ByteCount, data_offset));
3956 (struct dfs_referral_level_3 *)
3957 (8 /* sizeof start of data block */ +
3959 (char *) &pSMBr->hdr.Protocol);
3960 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
3961 le16_to_cpu(pSMBr->NumberOfReferrals),
3962 le16_to_cpu(pSMBr->DFSFlags),
3963 le16_to_cpu(referrals->ReferralSize),
3964 le16_to_cpu(referrals->ServerType),
3965 le16_to_cpu(referrals->ReferralFlags),
3966 le16_to_cpu(referrals->TimeToLive)));
3967 /* BB This field is actually two bytes in from start of
3968 data block so we could do safety check that DataBlock
3969 begins at address of pSMBr->NumberOfReferrals */
3970 *number_of_UNC_in_array =
3971 le16_to_cpu(pSMBr->NumberOfReferrals);
3973 /* BB Fix below so can return more than one referral */
3974 if (*number_of_UNC_in_array > 1)
3975 *number_of_UNC_in_array = 1;
3977 /* get the length of the strings describing refs */
3979 for (i = 0; i < *number_of_UNC_in_array; i++) {
3980 /* make sure that DfsPathOffset not past end */
3982 le16_to_cpu(referrals->DfsPathOffset);
3983 if (offset > data_count) {
3984 /* if invalid referral, stop here and do
3985 not try to copy any more */
3986 *number_of_UNC_in_array = i;
3989 temp = ((char *)referrals) + offset;
3991 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3992 name_len += UniStrnlen((wchar_t *)temp,
3995 name_len += strnlen(temp, data_count);
3998 /* BB add check that referral pointer does
3999 not fall off end PDU */
4001 /* BB add check for name_len bigger than bcc */
4003 kmalloc(name_len+1+(*number_of_UNC_in_array),
4005 if (*targetUNCs == NULL) {
4009 /* copy the ref strings */
4010 referrals = (struct dfs_referral_level_3 *)
4011 (8 /* sizeof data hdr */ + data_offset +
4012 (char *) &pSMBr->hdr.Protocol);
4014 for (i = 0; i < *number_of_UNC_in_array; i++) {
4015 temp = ((char *)referrals) +
4016 le16_to_cpu(referrals->DfsPathOffset);
4017 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
4018 cifs_strfromUCS_le(*targetUNCs,
4023 strncpy(*targetUNCs, temp, name_len);
4025 /* BB update target_uncs pointers */
4035 cifs_buf_release(pSMB);
4043 /* Query File System Info such as free space to old servers such as Win 9x */
4045 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4047 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4048 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4049 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4050 FILE_SYSTEM_ALLOC_INFO *response_data;
4052 int bytes_returned = 0;
4053 __u16 params, byte_count;
4055 cFYI(1, ("OldQFSInfo"));
4057 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4061 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4066 params = 2; /* level */
4067 pSMB->TotalDataCount = 0;
4068 pSMB->MaxParameterCount = cpu_to_le16(2);
4069 pSMB->MaxDataCount = cpu_to_le16(1000);
4070 pSMB->MaxSetupCount = 0;
4074 pSMB->Reserved2 = 0;
4075 byte_count = params + 1 /* pad */ ;
4076 pSMB->TotalParameterCount = cpu_to_le16(params);
4077 pSMB->ParameterCount = pSMB->TotalParameterCount;
4078 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4079 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4080 pSMB->DataCount = 0;
4081 pSMB->DataOffset = 0;
4082 pSMB->SetupCount = 1;
4083 pSMB->Reserved3 = 0;
4084 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4085 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4086 pSMB->hdr.smb_buf_length += byte_count;
4087 pSMB->ByteCount = cpu_to_le16(byte_count);
4089 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4090 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4092 cFYI(1, ("Send error in QFSInfo = %d", rc));
4093 } else { /* decode response */
4094 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4096 if (rc || (pSMBr->ByteCount < 18))
4097 rc = -EIO; /* bad smb */
4099 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4100 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4101 pSMBr->ByteCount, data_offset));
4103 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4104 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4106 le16_to_cpu(response_data->BytesPerSector) *
4107 le32_to_cpu(response_data->
4108 SectorsPerAllocationUnit);
4110 le32_to_cpu(response_data->TotalAllocationUnits);
4111 FSData->f_bfree = FSData->f_bavail =
4112 le32_to_cpu(response_data->FreeAllocationUnits);
4114 ("Blocks: %lld Free: %lld Block size %ld",
4115 (unsigned long long)FSData->f_blocks,
4116 (unsigned long long)FSData->f_bfree,
4120 cifs_buf_release(pSMB);
4123 goto oldQFSInfoRetry;
4129 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4131 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4132 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4133 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4134 FILE_SYSTEM_INFO *response_data;
4136 int bytes_returned = 0;
4137 __u16 params, byte_count;
4139 cFYI(1, ("In QFSInfo"));
4141 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4146 params = 2; /* level */
4147 pSMB->TotalDataCount = 0;
4148 pSMB->MaxParameterCount = cpu_to_le16(2);
4149 pSMB->MaxDataCount = cpu_to_le16(1000);
4150 pSMB->MaxSetupCount = 0;
4154 pSMB->Reserved2 = 0;
4155 byte_count = params + 1 /* pad */ ;
4156 pSMB->TotalParameterCount = cpu_to_le16(params);
4157 pSMB->ParameterCount = pSMB->TotalParameterCount;
4158 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4159 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4160 pSMB->DataCount = 0;
4161 pSMB->DataOffset = 0;
4162 pSMB->SetupCount = 1;
4163 pSMB->Reserved3 = 0;
4164 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4165 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4166 pSMB->hdr.smb_buf_length += byte_count;
4167 pSMB->ByteCount = cpu_to_le16(byte_count);
4169 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4170 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4172 cFYI(1, ("Send error in QFSInfo = %d", rc));
4173 } else { /* decode response */
4174 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4176 if (rc || (pSMBr->ByteCount < 24))
4177 rc = -EIO; /* bad smb */
4179 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4183 *) (((char *) &pSMBr->hdr.Protocol) +
4186 le32_to_cpu(response_data->BytesPerSector) *
4187 le32_to_cpu(response_data->
4188 SectorsPerAllocationUnit);
4190 le64_to_cpu(response_data->TotalAllocationUnits);
4191 FSData->f_bfree = FSData->f_bavail =
4192 le64_to_cpu(response_data->FreeAllocationUnits);
4194 ("Blocks: %lld Free: %lld Block size %ld",
4195 (unsigned long long)FSData->f_blocks,
4196 (unsigned long long)FSData->f_bfree,
4200 cifs_buf_release(pSMB);
4209 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4211 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4212 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4213 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4214 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4216 int bytes_returned = 0;
4217 __u16 params, byte_count;
4219 cFYI(1, ("In QFSAttributeInfo"));
4221 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4226 params = 2; /* level */
4227 pSMB->TotalDataCount = 0;
4228 pSMB->MaxParameterCount = cpu_to_le16(2);
4229 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4230 pSMB->MaxSetupCount = 0;
4234 pSMB->Reserved2 = 0;
4235 byte_count = params + 1 /* pad */ ;
4236 pSMB->TotalParameterCount = cpu_to_le16(params);
4237 pSMB->ParameterCount = pSMB->TotalParameterCount;
4238 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4239 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4240 pSMB->DataCount = 0;
4241 pSMB->DataOffset = 0;
4242 pSMB->SetupCount = 1;
4243 pSMB->Reserved3 = 0;
4244 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4245 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4246 pSMB->hdr.smb_buf_length += byte_count;
4247 pSMB->ByteCount = cpu_to_le16(byte_count);
4249 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4250 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4252 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4253 } else { /* decode response */
4254 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4256 if (rc || (pSMBr->ByteCount < 13)) {
4257 /* BB also check if enough bytes returned */
4258 rc = -EIO; /* bad smb */
4260 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4262 (FILE_SYSTEM_ATTRIBUTE_INFO
4263 *) (((char *) &pSMBr->hdr.Protocol) +
4265 memcpy(&tcon->fsAttrInfo, response_data,
4266 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4269 cifs_buf_release(pSMB);
4272 goto QFSAttributeRetry;
4278 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4280 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4281 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4282 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4283 FILE_SYSTEM_DEVICE_INFO *response_data;
4285 int bytes_returned = 0;
4286 __u16 params, byte_count;
4288 cFYI(1, ("In QFSDeviceInfo"));
4290 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4295 params = 2; /* level */
4296 pSMB->TotalDataCount = 0;
4297 pSMB->MaxParameterCount = cpu_to_le16(2);
4298 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4299 pSMB->MaxSetupCount = 0;
4303 pSMB->Reserved2 = 0;
4304 byte_count = params + 1 /* pad */ ;
4305 pSMB->TotalParameterCount = cpu_to_le16(params);
4306 pSMB->ParameterCount = pSMB->TotalParameterCount;
4307 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4308 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4310 pSMB->DataCount = 0;
4311 pSMB->DataOffset = 0;
4312 pSMB->SetupCount = 1;
4313 pSMB->Reserved3 = 0;
4314 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4315 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4316 pSMB->hdr.smb_buf_length += byte_count;
4317 pSMB->ByteCount = cpu_to_le16(byte_count);
4319 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4320 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4322 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4323 } else { /* decode response */
4324 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4326 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4327 rc = -EIO; /* bad smb */
4329 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4331 (FILE_SYSTEM_DEVICE_INFO *)
4332 (((char *) &pSMBr->hdr.Protocol) +
4334 memcpy(&tcon->fsDevInfo, response_data,
4335 sizeof (FILE_SYSTEM_DEVICE_INFO));
4338 cifs_buf_release(pSMB);
4341 goto QFSDeviceRetry;
4347 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4349 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4350 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4351 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4352 FILE_SYSTEM_UNIX_INFO *response_data;
4354 int bytes_returned = 0;
4355 __u16 params, byte_count;
4357 cFYI(1, ("In QFSUnixInfo"));
4359 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4364 params = 2; /* level */
4365 pSMB->TotalDataCount = 0;
4366 pSMB->DataCount = 0;
4367 pSMB->DataOffset = 0;
4368 pSMB->MaxParameterCount = cpu_to_le16(2);
4369 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4370 pSMB->MaxSetupCount = 0;
4374 pSMB->Reserved2 = 0;
4375 byte_count = params + 1 /* pad */ ;
4376 pSMB->ParameterCount = cpu_to_le16(params);
4377 pSMB->TotalParameterCount = pSMB->ParameterCount;
4378 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4379 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4380 pSMB->SetupCount = 1;
4381 pSMB->Reserved3 = 0;
4382 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4383 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4384 pSMB->hdr.smb_buf_length += byte_count;
4385 pSMB->ByteCount = cpu_to_le16(byte_count);
4387 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4388 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4390 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4391 } else { /* decode response */
4392 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4394 if (rc || (pSMBr->ByteCount < 13)) {
4395 rc = -EIO; /* bad smb */
4397 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4399 (FILE_SYSTEM_UNIX_INFO
4400 *) (((char *) &pSMBr->hdr.Protocol) +
4402 memcpy(&tcon->fsUnixInfo, response_data,
4403 sizeof (FILE_SYSTEM_UNIX_INFO));
4406 cifs_buf_release(pSMB);
4416 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4418 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4419 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4420 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4422 int bytes_returned = 0;
4423 __u16 params, param_offset, offset, byte_count;
4425 cFYI(1, ("In SETFSUnixInfo"));
4427 /* BB switch to small buf init to save memory */
4428 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4433 params = 4; /* 2 bytes zero followed by info level. */
4434 pSMB->MaxSetupCount = 0;
4438 pSMB->Reserved2 = 0;
4439 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4441 offset = param_offset + params;
4443 pSMB->MaxParameterCount = cpu_to_le16(4);
4444 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4445 pSMB->SetupCount = 1;
4446 pSMB->Reserved3 = 0;
4447 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4448 byte_count = 1 /* pad */ + params + 12;
4450 pSMB->DataCount = cpu_to_le16(12);
4451 pSMB->ParameterCount = cpu_to_le16(params);
4452 pSMB->TotalDataCount = pSMB->DataCount;
4453 pSMB->TotalParameterCount = pSMB->ParameterCount;
4454 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4455 pSMB->DataOffset = cpu_to_le16(offset);
4459 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4462 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4463 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4464 pSMB->ClientUnixCap = cpu_to_le64(cap);
4466 pSMB->hdr.smb_buf_length += byte_count;
4467 pSMB->ByteCount = cpu_to_le16(byte_count);
4469 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4470 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4472 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4473 } else { /* decode response */
4474 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4476 rc = -EIO; /* bad smb */
4479 cifs_buf_release(pSMB);
4482 goto SETFSUnixRetry;
4490 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4491 struct kstatfs *FSData)
4493 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4494 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4495 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4496 FILE_SYSTEM_POSIX_INFO *response_data;
4498 int bytes_returned = 0;
4499 __u16 params, byte_count;
4501 cFYI(1, ("In QFSPosixInfo"));
4503 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4508 params = 2; /* level */
4509 pSMB->TotalDataCount = 0;
4510 pSMB->DataCount = 0;
4511 pSMB->DataOffset = 0;
4512 pSMB->MaxParameterCount = cpu_to_le16(2);
4513 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4514 pSMB->MaxSetupCount = 0;
4518 pSMB->Reserved2 = 0;
4519 byte_count = params + 1 /* pad */ ;
4520 pSMB->ParameterCount = cpu_to_le16(params);
4521 pSMB->TotalParameterCount = pSMB->ParameterCount;
4522 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4523 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4524 pSMB->SetupCount = 1;
4525 pSMB->Reserved3 = 0;
4526 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4527 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4528 pSMB->hdr.smb_buf_length += byte_count;
4529 pSMB->ByteCount = cpu_to_le16(byte_count);
4531 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4532 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4534 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4535 } else { /* decode response */
4536 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4538 if (rc || (pSMBr->ByteCount < 13)) {
4539 rc = -EIO; /* bad smb */
4541 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4543 (FILE_SYSTEM_POSIX_INFO
4544 *) (((char *) &pSMBr->hdr.Protocol) +
4547 le32_to_cpu(response_data->BlockSize);
4549 le64_to_cpu(response_data->TotalBlocks);
4551 le64_to_cpu(response_data->BlocksAvail);
4552 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4553 FSData->f_bavail = FSData->f_bfree;
4556 le64_to_cpu(response_data->UserBlocksAvail);
4558 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4560 le64_to_cpu(response_data->TotalFileNodes);
4561 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4563 le64_to_cpu(response_data->FreeFileNodes);
4566 cifs_buf_release(pSMB);
4575 /* We can not use write of zero bytes trick to
4576 set file size due to need for large file support. Also note that
4577 this SetPathInfo is preferred to SetFileInfo based method in next
4578 routine which is only needed to work around a sharing violation bug
4579 in Samba which this routine can run into */
4582 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4583 __u64 size, int SetAllocation,
4584 const struct nls_table *nls_codepage, int remap)
4586 struct smb_com_transaction2_spi_req *pSMB = NULL;
4587 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4588 struct file_end_of_file_info *parm_data;
4591 int bytes_returned = 0;
4592 __u16 params, byte_count, data_count, param_offset, offset;
4594 cFYI(1, ("In SetEOF"));
4596 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4601 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4603 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4604 PATH_MAX, nls_codepage, remap);
4605 name_len++; /* trailing null */
4607 } else { /* BB improve the check for buffer overruns BB */
4608 name_len = strnlen(fileName, PATH_MAX);
4609 name_len++; /* trailing null */
4610 strncpy(pSMB->FileName, fileName, name_len);
4612 params = 6 + name_len;
4613 data_count = sizeof (struct file_end_of_file_info);
4614 pSMB->MaxParameterCount = cpu_to_le16(2);
4615 pSMB->MaxDataCount = cpu_to_le16(4100);
4616 pSMB->MaxSetupCount = 0;
4620 pSMB->Reserved2 = 0;
4621 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4622 InformationLevel) - 4;
4623 offset = param_offset + params;
4624 if (SetAllocation) {
4625 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4626 pSMB->InformationLevel =
4627 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4629 pSMB->InformationLevel =
4630 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4631 } else /* Set File Size */ {
4632 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4633 pSMB->InformationLevel =
4634 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4636 pSMB->InformationLevel =
4637 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4641 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4643 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4644 pSMB->DataOffset = cpu_to_le16(offset);
4645 pSMB->SetupCount = 1;
4646 pSMB->Reserved3 = 0;
4647 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4648 byte_count = 3 /* pad */ + params + data_count;
4649 pSMB->DataCount = cpu_to_le16(data_count);
4650 pSMB->TotalDataCount = pSMB->DataCount;
4651 pSMB->ParameterCount = cpu_to_le16(params);
4652 pSMB->TotalParameterCount = pSMB->ParameterCount;
4653 pSMB->Reserved4 = 0;
4654 pSMB->hdr.smb_buf_length += byte_count;
4655 parm_data->FileSize = cpu_to_le64(size);
4656 pSMB->ByteCount = cpu_to_le16(byte_count);
4657 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4658 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4660 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4663 cifs_buf_release(pSMB);
4672 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4673 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4675 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4676 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4678 struct file_end_of_file_info *parm_data;
4680 int bytes_returned = 0;
4681 __u16 params, param_offset, offset, byte_count, count;
4683 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4685 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4690 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4692 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4693 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4696 pSMB->MaxSetupCount = 0;
4700 pSMB->Reserved2 = 0;
4701 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4702 offset = param_offset + params;
4704 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4706 count = sizeof(struct file_end_of_file_info);
4707 pSMB->MaxParameterCount = cpu_to_le16(2);
4708 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4709 pSMB->SetupCount = 1;
4710 pSMB->Reserved3 = 0;
4711 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4712 byte_count = 3 /* pad */ + params + count;
4713 pSMB->DataCount = cpu_to_le16(count);
4714 pSMB->ParameterCount = cpu_to_le16(params);
4715 pSMB->TotalDataCount = pSMB->DataCount;
4716 pSMB->TotalParameterCount = pSMB->ParameterCount;
4717 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4719 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4721 pSMB->DataOffset = cpu_to_le16(offset);
4722 parm_data->FileSize = cpu_to_le64(size);
4724 if (SetAllocation) {
4725 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4726 pSMB->InformationLevel =
4727 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4729 pSMB->InformationLevel =
4730 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4731 } else /* Set File Size */ {
4732 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4733 pSMB->InformationLevel =
4734 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4736 pSMB->InformationLevel =
4737 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4739 pSMB->Reserved4 = 0;
4740 pSMB->hdr.smb_buf_length += byte_count;
4741 pSMB->ByteCount = cpu_to_le16(byte_count);
4742 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4743 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4746 ("Send error in SetFileInfo (SetFileSize) = %d",
4751 cifs_small_buf_release(pSMB);
4753 /* Note: On -EAGAIN error only caller can retry on handle based calls
4754 since file handle passed in no longer valid */
4759 /* Some legacy servers such as NT4 require that the file times be set on
4760 an open handle, rather than by pathname - this is awkward due to
4761 potential access conflicts on the open, but it is unavoidable for these
4762 old servers since the only other choice is to go from 100 nanosecond DCE
4763 time and resort to the original setpathinfo level which takes the ancient
4764 DOS time format with 2 second granularity */
4766 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4767 const FILE_BASIC_INFO *data, __u16 fid)
4769 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4770 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4773 int bytes_returned = 0;
4774 __u16 params, param_offset, offset, byte_count, count;
4776 cFYI(1, ("Set Times (via SetFileInfo)"));
4777 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4782 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4784 /* At this point there is no need to override the current pid
4785 with the pid of the opener, but that could change if we someday
4786 use an existing handle (rather than opening one on the fly) */
4787 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4788 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4791 pSMB->MaxSetupCount = 0;
4795 pSMB->Reserved2 = 0;
4796 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4797 offset = param_offset + params;
4799 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4801 count = sizeof (FILE_BASIC_INFO);
4802 pSMB->MaxParameterCount = cpu_to_le16(2);
4803 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4804 pSMB->SetupCount = 1;
4805 pSMB->Reserved3 = 0;
4806 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4807 byte_count = 3 /* pad */ + params + count;
4808 pSMB->DataCount = cpu_to_le16(count);
4809 pSMB->ParameterCount = cpu_to_le16(params);
4810 pSMB->TotalDataCount = pSMB->DataCount;
4811 pSMB->TotalParameterCount = pSMB->ParameterCount;
4812 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4813 pSMB->DataOffset = cpu_to_le16(offset);
4815 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4816 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4818 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4819 pSMB->Reserved4 = 0;
4820 pSMB->hdr.smb_buf_length += byte_count;
4821 pSMB->ByteCount = cpu_to_le16(byte_count);
4822 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4823 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4824 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4826 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4829 cifs_small_buf_release(pSMB);
4831 /* Note: On -EAGAIN error only caller can retry on handle based calls
4832 since file handle passed in no longer valid */
4839 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4840 const FILE_BASIC_INFO *data,
4841 const struct nls_table *nls_codepage, int remap)
4843 TRANSACTION2_SPI_REQ *pSMB = NULL;
4844 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4847 int bytes_returned = 0;
4849 __u16 params, param_offset, offset, byte_count, count;
4851 cFYI(1, ("In SetTimes"));
4854 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4859 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4861 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4862 PATH_MAX, nls_codepage, remap);
4863 name_len++; /* trailing null */
4865 } else { /* BB improve the check for buffer overruns BB */
4866 name_len = strnlen(fileName, PATH_MAX);
4867 name_len++; /* trailing null */
4868 strncpy(pSMB->FileName, fileName, name_len);
4871 params = 6 + name_len;
4872 count = sizeof (FILE_BASIC_INFO);
4873 pSMB->MaxParameterCount = cpu_to_le16(2);
4874 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4875 pSMB->MaxSetupCount = 0;
4879 pSMB->Reserved2 = 0;
4880 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4881 InformationLevel) - 4;
4882 offset = param_offset + params;
4883 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4884 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4885 pSMB->DataOffset = cpu_to_le16(offset);
4886 pSMB->SetupCount = 1;
4887 pSMB->Reserved3 = 0;
4888 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4889 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 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4896 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4898 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4899 pSMB->Reserved4 = 0;
4900 pSMB->hdr.smb_buf_length += byte_count;
4901 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4902 pSMB->ByteCount = cpu_to_le16(byte_count);
4903 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4904 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4906 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4909 cifs_buf_release(pSMB);
4917 /* Can not be used to set time stamps yet (due to old DOS time format) */
4918 /* Can be used to set attributes */
4919 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4920 handling it anyway and NT4 was what we thought it would be needed for
4921 Do not delete it until we prove whether needed for Win9x though */
4923 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4924 __u16 dos_attrs, const struct nls_table *nls_codepage)
4926 SETATTR_REQ *pSMB = NULL;
4927 SETATTR_RSP *pSMBr = NULL;
4932 cFYI(1, ("In SetAttrLegacy"));
4935 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4940 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4942 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4943 PATH_MAX, nls_codepage);
4944 name_len++; /* trailing null */
4946 } else { /* BB improve the check for buffer overruns BB */
4947 name_len = strnlen(fileName, PATH_MAX);
4948 name_len++; /* trailing null */
4949 strncpy(pSMB->fileName, fileName, name_len);
4951 pSMB->attr = cpu_to_le16(dos_attrs);
4952 pSMB->BufferFormat = 0x04;
4953 pSMB->hdr.smb_buf_length += name_len + 1;
4954 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4955 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4956 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4958 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4961 cifs_buf_release(pSMB);
4964 goto SetAttrLgcyRetry;
4968 #endif /* temporarily unneeded SetAttr legacy function */
4971 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4972 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4973 dev_t device, const struct nls_table *nls_codepage,
4976 TRANSACTION2_SPI_REQ *pSMB = NULL;
4977 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4980 int bytes_returned = 0;
4981 FILE_UNIX_BASIC_INFO *data_offset;
4982 __u16 params, param_offset, offset, count, byte_count;
4984 cFYI(1, ("In SetUID/GID/Mode"));
4986 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4991 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4993 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4994 PATH_MAX, nls_codepage, remap);
4995 name_len++; /* trailing null */
4997 } else { /* BB improve the check for buffer overruns BB */
4998 name_len = strnlen(fileName, PATH_MAX);
4999 name_len++; /* trailing null */
5000 strncpy(pSMB->FileName, fileName, name_len);
5003 params = 6 + name_len;
5004 count = sizeof (FILE_UNIX_BASIC_INFO);
5005 pSMB->MaxParameterCount = cpu_to_le16(2);
5006 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5007 pSMB->MaxSetupCount = 0;
5011 pSMB->Reserved2 = 0;
5012 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5013 InformationLevel) - 4;
5014 offset = param_offset + params;
5016 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5018 memset(data_offset, 0, count);
5019 pSMB->DataOffset = cpu_to_le16(offset);
5020 pSMB->ParameterOffset = cpu_to_le16(param_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;
5025 pSMB->ParameterCount = cpu_to_le16(params);
5026 pSMB->DataCount = cpu_to_le16(count);
5027 pSMB->TotalParameterCount = pSMB->ParameterCount;
5028 pSMB->TotalDataCount = pSMB->DataCount;
5029 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5030 pSMB->Reserved4 = 0;
5031 pSMB->hdr.smb_buf_length += byte_count;
5032 /* Samba server ignores set of file size to zero due to bugs in some
5033 older clients, but we should be precise - we use SetFileSize to
5034 set file size and do not want to truncate file size to zero
5035 accidently as happened on one Samba server beta by putting
5036 zero instead of -1 here */
5037 data_offset->EndOfFile = NO_CHANGE_64;
5038 data_offset->NumOfBytes = NO_CHANGE_64;
5039 data_offset->LastStatusChange = NO_CHANGE_64;
5040 data_offset->LastAccessTime = NO_CHANGE_64;
5041 data_offset->LastModificationTime = NO_CHANGE_64;
5042 data_offset->Uid = cpu_to_le64(uid);
5043 data_offset->Gid = cpu_to_le64(gid);
5044 /* better to leave device as zero when it is */
5045 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
5046 data_offset->DevMinor = cpu_to_le64(MINOR(device));
5047 data_offset->Permissions = cpu_to_le64(mode);
5050 data_offset->Type = cpu_to_le32(UNIX_FILE);
5051 else if (S_ISDIR(mode))
5052 data_offset->Type = cpu_to_le32(UNIX_DIR);
5053 else if (S_ISLNK(mode))
5054 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5055 else if (S_ISCHR(mode))
5056 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5057 else if (S_ISBLK(mode))
5058 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5059 else if (S_ISFIFO(mode))
5060 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5061 else if (S_ISSOCK(mode))
5062 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5065 pSMB->ByteCount = cpu_to_le16(byte_count);
5066 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5067 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5069 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5073 cifs_buf_release(pSMB);
5079 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5080 const int notify_subdirs, const __u16 netfid,
5081 __u32 filter, struct file *pfile, int multishot,
5082 const struct nls_table *nls_codepage)
5085 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5086 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5087 struct dir_notify_req *dnotify_req;
5090 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5091 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5096 pSMB->TotalParameterCount = 0 ;
5097 pSMB->TotalDataCount = 0;
5098 pSMB->MaxParameterCount = cpu_to_le32(2);
5099 /* BB find exact data count max from sess structure BB */
5100 pSMB->MaxDataCount = 0; /* same in little endian or be */
5101 /* BB VERIFY verify which is correct for above BB */
5102 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5103 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5105 pSMB->MaxSetupCount = 4;
5107 pSMB->ParameterOffset = 0;
5108 pSMB->DataCount = 0;
5109 pSMB->DataOffset = 0;
5110 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5111 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5112 pSMB->ParameterCount = pSMB->TotalParameterCount;
5114 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5115 pSMB->Reserved2 = 0;
5116 pSMB->CompletionFilter = cpu_to_le32(filter);
5117 pSMB->Fid = netfid; /* file handle always le */
5118 pSMB->ByteCount = 0;
5120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5121 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5123 cFYI(1, ("Error in Notify = %d", rc));
5125 /* Add file to outstanding requests */
5126 /* BB change to kmem cache alloc */
5127 dnotify_req = kmalloc(
5128 sizeof(struct dir_notify_req),
5131 dnotify_req->Pid = pSMB->hdr.Pid;
5132 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5133 dnotify_req->Mid = pSMB->hdr.Mid;
5134 dnotify_req->Tid = pSMB->hdr.Tid;
5135 dnotify_req->Uid = pSMB->hdr.Uid;
5136 dnotify_req->netfid = netfid;
5137 dnotify_req->pfile = pfile;
5138 dnotify_req->filter = filter;
5139 dnotify_req->multishot = multishot;
5140 spin_lock(&GlobalMid_Lock);
5141 list_add_tail(&dnotify_req->lhead,
5142 &GlobalDnotifyReqList);
5143 spin_unlock(&GlobalMid_Lock);
5147 cifs_buf_release(pSMB);
5150 #ifdef CONFIG_CIFS_XATTR
5152 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5153 const unsigned char *searchName,
5154 char *EAData, size_t buf_size,
5155 const struct nls_table *nls_codepage, int remap)
5157 /* BB assumes one setup word */
5158 TRANSACTION2_QPI_REQ *pSMB = NULL;
5159 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5163 struct fea *temp_fea;
5165 __u16 params, byte_count;
5167 cFYI(1, ("In Query All EAs path %s", searchName));
5169 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5174 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5176 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5177 PATH_MAX, nls_codepage, remap);
5178 name_len++; /* trailing null */
5180 } else { /* BB improve the check for buffer overruns BB */
5181 name_len = strnlen(searchName, PATH_MAX);
5182 name_len++; /* trailing null */
5183 strncpy(pSMB->FileName, searchName, name_len);
5186 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5187 pSMB->TotalDataCount = 0;
5188 pSMB->MaxParameterCount = cpu_to_le16(2);
5189 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5190 pSMB->MaxSetupCount = 0;
5194 pSMB->Reserved2 = 0;
5195 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5196 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5197 pSMB->DataCount = 0;
5198 pSMB->DataOffset = 0;
5199 pSMB->SetupCount = 1;
5200 pSMB->Reserved3 = 0;
5201 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5202 byte_count = params + 1 /* pad */ ;
5203 pSMB->TotalParameterCount = cpu_to_le16(params);
5204 pSMB->ParameterCount = pSMB->TotalParameterCount;
5205 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5206 pSMB->Reserved4 = 0;
5207 pSMB->hdr.smb_buf_length += byte_count;
5208 pSMB->ByteCount = cpu_to_le16(byte_count);
5210 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5211 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5213 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5214 } else { /* decode response */
5215 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5217 /* BB also check enough total bytes returned */
5218 /* BB we need to improve the validity checking
5219 of these trans2 responses */
5220 if (rc || (pSMBr->ByteCount < 4))
5221 rc = -EIO; /* bad smb */
5222 /* else if (pFindData){
5223 memcpy((char *) pFindData,
5224 (char *) &pSMBr->hdr.Protocol +
5227 /* check that length of list is not more than bcc */
5228 /* check that each entry does not go beyond length
5230 /* check that each element of each entry does not
5231 go beyond end of list */
5232 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5233 struct fealist *ea_response_data;
5235 /* validate_trans2_offsets() */
5236 /* BB check if start of smb + data_offset > &bcc+ bcc */
5237 ea_response_data = (struct fealist *)
5238 (((char *) &pSMBr->hdr.Protocol) +
5240 name_len = le32_to_cpu(ea_response_data->list_len);
5241 cFYI(1, ("ea length %d", name_len));
5242 if (name_len <= 8) {
5243 /* returned EA size zeroed at top of function */
5244 cFYI(1, ("empty EA list returned from server"));
5246 /* account for ea list len */
5248 temp_fea = ea_response_data->list;
5249 temp_ptr = (char *)temp_fea;
5250 while (name_len > 0) {
5254 rc += temp_fea->name_len;
5255 /* account for prefix user. and trailing null */
5257 if (rc < (int)buf_size) {
5258 memcpy(EAData, "user.", 5);
5260 memcpy(EAData, temp_ptr,
5261 temp_fea->name_len);
5262 EAData += temp_fea->name_len;
5263 /* null terminate name */
5265 EAData = EAData + 1;
5266 } else if (buf_size == 0) {
5267 /* skip copy - calc size only */
5269 /* stop before overrun buffer */
5273 name_len -= temp_fea->name_len;
5274 temp_ptr += temp_fea->name_len;
5275 /* account for trailing null */
5279 le16_to_cpu(temp_fea->value_len);
5280 name_len -= value_len;
5281 temp_ptr += value_len;
5282 /* BB check that temp_ptr is still
5285 /* no trailing null to account for
5287 /* go on to next EA */
5288 temp_fea = (struct fea *)temp_ptr;
5294 cifs_buf_release(pSMB);
5301 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5302 const unsigned char *searchName, const unsigned char *ea_name,
5303 unsigned char *ea_value, size_t buf_size,
5304 const struct nls_table *nls_codepage, int remap)
5306 TRANSACTION2_QPI_REQ *pSMB = NULL;
5307 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5311 struct fea *temp_fea;
5313 __u16 params, byte_count;
5315 cFYI(1, ("In Query EA path %s", searchName));
5317 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5322 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5324 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5325 PATH_MAX, nls_codepage, remap);
5326 name_len++; /* trailing null */
5328 } else { /* BB improve the check for buffer overruns BB */
5329 name_len = strnlen(searchName, PATH_MAX);
5330 name_len++; /* trailing null */
5331 strncpy(pSMB->FileName, searchName, name_len);
5334 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5335 pSMB->TotalDataCount = 0;
5336 pSMB->MaxParameterCount = cpu_to_le16(2);
5337 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5338 pSMB->MaxSetupCount = 0;
5342 pSMB->Reserved2 = 0;
5343 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5344 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5345 pSMB->DataCount = 0;
5346 pSMB->DataOffset = 0;
5347 pSMB->SetupCount = 1;
5348 pSMB->Reserved3 = 0;
5349 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5350 byte_count = params + 1 /* pad */ ;
5351 pSMB->TotalParameterCount = cpu_to_le16(params);
5352 pSMB->ParameterCount = pSMB->TotalParameterCount;
5353 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5354 pSMB->Reserved4 = 0;
5355 pSMB->hdr.smb_buf_length += byte_count;
5356 pSMB->ByteCount = cpu_to_le16(byte_count);
5358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5359 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5361 cFYI(1, ("Send error in Query EA = %d", rc));
5362 } else { /* decode response */
5363 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5365 /* BB also check enough total bytes returned */
5366 /* BB we need to improve the validity checking
5367 of these trans2 responses */
5368 if (rc || (pSMBr->ByteCount < 4))
5369 rc = -EIO; /* bad smb */
5370 /* else if (pFindData){
5371 memcpy((char *) pFindData,
5372 (char *) &pSMBr->hdr.Protocol +
5375 /* check that length of list is not more than bcc */
5376 /* check that each entry does not go beyond length
5378 /* check that each element of each entry does not
5379 go beyond end of list */
5380 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5381 struct fealist *ea_response_data;
5383 /* validate_trans2_offsets() */
5384 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5385 ea_response_data = (struct fealist *)
5386 (((char *) &pSMBr->hdr.Protocol) +
5388 name_len = le32_to_cpu(ea_response_data->list_len);
5389 cFYI(1, ("ea length %d", name_len));
5390 if (name_len <= 8) {
5391 /* returned EA size zeroed at top of function */
5392 cFYI(1, ("empty EA list returned from server"));
5394 /* account for ea list len */
5396 temp_fea = ea_response_data->list;
5397 temp_ptr = (char *)temp_fea;
5398 /* loop through checking if we have a matching
5399 name and then return the associated value */
5400 while (name_len > 0) {
5405 le16_to_cpu(temp_fea->value_len);
5406 /* BB validate that value_len falls within SMB,
5407 even though maximum for name_len is 255 */
5408 if (memcmp(temp_fea->name, ea_name,
5409 temp_fea->name_len) == 0) {
5412 /* account for prefix user. and trailing null */
5413 if (rc <= (int)buf_size) {
5415 temp_fea->name+temp_fea->name_len+1,
5417 /* ea values, unlike ea
5420 } else if (buf_size == 0) {
5421 /* skip copy - calc size only */
5423 /* stop before overrun buffer */
5428 name_len -= temp_fea->name_len;
5429 temp_ptr += temp_fea->name_len;
5430 /* account for trailing null */
5433 name_len -= value_len;
5434 temp_ptr += value_len;
5435 /* No trailing null to account for in
5436 value_len. Go on to next EA */
5437 temp_fea = (struct fea *)temp_ptr;
5443 cifs_buf_release(pSMB);
5451 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5452 const char *ea_name, const void *ea_value,
5453 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5456 struct smb_com_transaction2_spi_req *pSMB = NULL;
5457 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5458 struct fealist *parm_data;
5461 int bytes_returned = 0;
5462 __u16 params, param_offset, byte_count, offset, count;
5464 cFYI(1, ("In SetEA"));
5466 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5471 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5473 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5474 PATH_MAX, nls_codepage, remap);
5475 name_len++; /* trailing null */
5477 } else { /* BB improve the check for buffer overruns BB */
5478 name_len = strnlen(fileName, PATH_MAX);
5479 name_len++; /* trailing null */
5480 strncpy(pSMB->FileName, fileName, name_len);
5483 params = 6 + name_len;
5485 /* done calculating parms using name_len of file name,
5486 now use name_len to calculate length of ea name
5487 we are going to create in the inode xattrs */
5488 if (ea_name == NULL)
5491 name_len = strnlen(ea_name, 255);
5493 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5494 pSMB->MaxParameterCount = cpu_to_le16(2);
5495 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5496 pSMB->MaxSetupCount = 0;
5500 pSMB->Reserved2 = 0;
5501 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5502 InformationLevel) - 4;
5503 offset = param_offset + params;
5504 pSMB->InformationLevel =
5505 cpu_to_le16(SMB_SET_FILE_EA);
5508 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5510 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5511 pSMB->DataOffset = cpu_to_le16(offset);
5512 pSMB->SetupCount = 1;
5513 pSMB->Reserved3 = 0;
5514 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5515 byte_count = 3 /* pad */ + params + count;
5516 pSMB->DataCount = cpu_to_le16(count);
5517 parm_data->list_len = cpu_to_le32(count);
5518 parm_data->list[0].EA_flags = 0;
5519 /* we checked above that name len is less than 255 */
5520 parm_data->list[0].name_len = (__u8)name_len;
5521 /* EA names are always ASCII */
5523 strncpy(parm_data->list[0].name, ea_name, name_len);
5524 parm_data->list[0].name[name_len] = 0;
5525 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5526 /* caller ensures that ea_value_len is less than 64K but
5527 we need to ensure that it fits within the smb */
5529 /*BB add length check to see if it would fit in
5530 negotiated SMB buffer size BB */
5531 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5533 memcpy(parm_data->list[0].name+name_len+1,
5534 ea_value, ea_value_len);
5536 pSMB->TotalDataCount = pSMB->DataCount;
5537 pSMB->ParameterCount = cpu_to_le16(params);
5538 pSMB->TotalParameterCount = pSMB->ParameterCount;
5539 pSMB->Reserved4 = 0;
5540 pSMB->hdr.smb_buf_length += byte_count;
5541 pSMB->ByteCount = cpu_to_le16(byte_count);
5542 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5543 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5545 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5548 cifs_buf_release(pSMB);