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 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
793 const struct nls_table *nls_codepage, int remap)
795 DELETE_FILE_REQ *pSMB = NULL;
796 DELETE_FILE_RSP *pSMBr = NULL;
802 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
807 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
809 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
810 PATH_MAX, nls_codepage, remap);
811 name_len++; /* trailing null */
813 } else { /* BB improve check for buffer overruns BB */
814 name_len = strnlen(fileName, PATH_MAX);
815 name_len++; /* trailing null */
816 strncpy(pSMB->fileName, fileName, name_len);
818 pSMB->SearchAttributes =
819 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
820 pSMB->BufferFormat = 0x04;
821 pSMB->hdr.smb_buf_length += name_len + 1;
822 pSMB->ByteCount = cpu_to_le16(name_len + 1);
823 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
824 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
825 cifs_stats_inc(&tcon->num_deletes);
827 cFYI(1, ("Error in RMFile = %d", rc));
830 cifs_buf_release(pSMB);
838 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
839 const struct nls_table *nls_codepage, int remap)
841 DELETE_DIRECTORY_REQ *pSMB = NULL;
842 DELETE_DIRECTORY_RSP *pSMBr = NULL;
847 cFYI(1, ("In CIFSSMBRmDir"));
849 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
854 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
855 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
856 PATH_MAX, nls_codepage, remap);
857 name_len++; /* trailing null */
859 } else { /* BB improve check for buffer overruns BB */
860 name_len = strnlen(dirName, PATH_MAX);
861 name_len++; /* trailing null */
862 strncpy(pSMB->DirName, dirName, name_len);
865 pSMB->BufferFormat = 0x04;
866 pSMB->hdr.smb_buf_length += name_len + 1;
867 pSMB->ByteCount = cpu_to_le16(name_len + 1);
868 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
870 cifs_stats_inc(&tcon->num_rmdirs);
872 cFYI(1, ("Error in RMDir = %d", rc));
875 cifs_buf_release(pSMB);
882 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
883 const char *name, const struct nls_table *nls_codepage, int remap)
886 CREATE_DIRECTORY_REQ *pSMB = NULL;
887 CREATE_DIRECTORY_RSP *pSMBr = NULL;
891 cFYI(1, ("In CIFSSMBMkDir"));
893 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
898 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
899 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
900 PATH_MAX, nls_codepage, remap);
901 name_len++; /* trailing null */
903 } else { /* BB improve check for buffer overruns BB */
904 name_len = strnlen(name, PATH_MAX);
905 name_len++; /* trailing null */
906 strncpy(pSMB->DirName, name, name_len);
909 pSMB->BufferFormat = 0x04;
910 pSMB->hdr.smb_buf_length += name_len + 1;
911 pSMB->ByteCount = cpu_to_le16(name_len + 1);
912 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
913 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
914 cifs_stats_inc(&tcon->num_mkdirs);
916 cFYI(1, ("Error in Mkdir = %d", rc));
919 cifs_buf_release(pSMB);
926 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
927 __u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
928 __u32 *pOplock, const char *name,
929 const struct nls_table *nls_codepage, int remap)
931 TRANSACTION2_SPI_REQ *pSMB = NULL;
932 TRANSACTION2_SPI_RSP *pSMBr = NULL;
935 int bytes_returned = 0;
937 __u16 params, param_offset, offset, byte_count, count;
938 OPEN_PSX_REQ * pdata;
939 OPEN_PSX_RSP * psx_rsp;
941 cFYI(1, ("In POSIX Create"));
943 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
948 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
950 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
951 PATH_MAX, nls_codepage, remap);
952 name_len++; /* trailing null */
954 } else { /* BB improve the check for buffer overruns BB */
955 name_len = strnlen(name, PATH_MAX);
956 name_len++; /* trailing null */
957 strncpy(pSMB->FileName, name, name_len);
960 params = 6 + name_len;
961 count = sizeof(OPEN_PSX_REQ);
962 pSMB->MaxParameterCount = cpu_to_le16(2);
963 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
964 pSMB->MaxSetupCount = 0;
969 param_offset = offsetof(struct smb_com_transaction2_spi_req,
970 InformationLevel) - 4;
971 offset = param_offset + params;
972 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
973 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
974 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
975 pdata->Permissions = cpu_to_le64(mode);
976 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
977 pdata->OpenFlags = cpu_to_le32(*pOplock);
978 pSMB->ParameterOffset = cpu_to_le16(param_offset);
979 pSMB->DataOffset = cpu_to_le16(offset);
980 pSMB->SetupCount = 1;
982 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
983 byte_count = 3 /* pad */ + params + count;
985 pSMB->DataCount = cpu_to_le16(count);
986 pSMB->ParameterCount = cpu_to_le16(params);
987 pSMB->TotalDataCount = pSMB->DataCount;
988 pSMB->TotalParameterCount = pSMB->ParameterCount;
989 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
991 pSMB->hdr.smb_buf_length += byte_count;
992 pSMB->ByteCount = cpu_to_le16(byte_count);
993 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
994 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
996 cFYI(1, ("Posix create returned %d", rc));
1000 cFYI(1, ("copying inode info"));
1001 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1003 if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1004 rc = -EIO; /* bad smb */
1005 goto psx_create_err;
1008 /* copy return information to pRetData */
1009 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1010 + le16_to_cpu(pSMBr->t2.DataOffset));
1012 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1014 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1015 /* Let caller know file was created so we can set the mode. */
1016 /* Do we care about the CreateAction in any other cases? */
1017 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1018 *pOplock |= CIFS_CREATE_ACTION;
1019 /* check to make sure response data is there */
1020 if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) {
1021 pRetData->Type = -1; /* unknown */
1022 #ifdef CONFIG_CIFS_DEBUG2
1023 cFYI(1, ("unknown type"));
1026 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1027 + sizeof(FILE_UNIX_BASIC_INFO)) {
1028 cERROR(1, ("Open response data too small"));
1029 pRetData->Type = -1;
1030 goto psx_create_err;
1032 memcpy((char *) pRetData,
1033 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1034 sizeof (FILE_UNIX_BASIC_INFO));
1038 cifs_buf_release(pSMB);
1040 cifs_stats_inc(&tcon->num_mkdirs);
1048 static __u16 convert_disposition(int disposition)
1052 switch (disposition) {
1053 case FILE_SUPERSEDE:
1054 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1057 ofun = SMBOPEN_OAPPEND;
1060 ofun = SMBOPEN_OCREATE;
1063 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1065 case FILE_OVERWRITE:
1066 ofun = SMBOPEN_OTRUNC;
1068 case FILE_OVERWRITE_IF:
1069 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1072 cFYI(1, ("unknown disposition %d", disposition));
1073 ofun = SMBOPEN_OAPPEND; /* regular open */
1079 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1080 const char *fileName, const int openDisposition,
1081 const int access_flags, const int create_options, __u16 * netfid,
1082 int *pOplock, FILE_ALL_INFO * pfile_info,
1083 const struct nls_table *nls_codepage, int remap)
1086 OPENX_REQ *pSMB = NULL;
1087 OPENX_RSP *pSMBr = NULL;
1093 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1098 pSMB->AndXCommand = 0xFF; /* none */
1100 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1101 count = 1; /* account for one byte pad to word boundary */
1103 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1104 fileName, PATH_MAX, nls_codepage, remap);
1105 name_len++; /* trailing null */
1107 } else { /* BB improve check for buffer overruns BB */
1108 count = 0; /* no pad */
1109 name_len = strnlen(fileName, PATH_MAX);
1110 name_len++; /* trailing null */
1111 strncpy(pSMB->fileName, fileName, name_len);
1113 if (*pOplock & REQ_OPLOCK)
1114 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1115 else if (*pOplock & REQ_BATCHOPLOCK) {
1116 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1118 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1119 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1125 pSMB->Mode = cpu_to_le16(2);
1126 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1127 /* set file as system file if special file such
1128 as fifo and server expecting SFU style and
1129 no Unix extensions */
1131 if (create_options & CREATE_OPTION_SPECIAL)
1132 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1134 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
1136 /* if ((omode & S_IWUGO) == 0)
1137 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1138 /* Above line causes problems due to vfs splitting create into two
1139 pieces - need to set mode after file created not while it is
1143 /* pSMB->CreateOptions = cpu_to_le32(create_options &
1144 CREATE_OPTIONS_MASK); */
1145 /* BB FIXME END BB */
1147 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1148 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1150 pSMB->hdr.smb_buf_length += count;
1152 pSMB->ByteCount = cpu_to_le16(count);
1153 /* long_op set to 1 to allow for oplock break timeouts */
1154 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1155 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1156 cifs_stats_inc(&tcon->num_opens);
1158 cFYI(1, ("Error in Open = %d", rc));
1160 /* BB verify if wct == 15 */
1162 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
1164 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1165 /* Let caller know file was created so we can set the mode. */
1166 /* Do we care about the CreateAction in any other cases? */
1168 /* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1169 *pOplock |= CIFS_CREATE_ACTION; */
1173 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1174 pfile_info->LastAccessTime = 0; /* BB fixme */
1175 pfile_info->LastWriteTime = 0; /* BB fixme */
1176 pfile_info->ChangeTime = 0; /* BB fixme */
1177 pfile_info->Attributes =
1178 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1179 /* the file_info buf is endian converted by caller */
1180 pfile_info->AllocationSize =
1181 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1182 pfile_info->EndOfFile = pfile_info->AllocationSize;
1183 pfile_info->NumberOfLinks = cpu_to_le32(1);
1187 cifs_buf_release(pSMB);
1194 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1195 const char *fileName, const int openDisposition,
1196 const int access_flags, const int create_options, __u16 * netfid,
1197 int *pOplock, FILE_ALL_INFO * pfile_info,
1198 const struct nls_table *nls_codepage, int remap)
1201 OPEN_REQ *pSMB = NULL;
1202 OPEN_RSP *pSMBr = NULL;
1208 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1213 pSMB->AndXCommand = 0xFF; /* none */
1215 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1216 count = 1; /* account for one byte pad to word boundary */
1218 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1219 fileName, PATH_MAX, nls_codepage, remap);
1220 name_len++; /* trailing null */
1222 pSMB->NameLength = cpu_to_le16(name_len);
1223 } else { /* BB improve check for buffer overruns BB */
1224 count = 0; /* no pad */
1225 name_len = strnlen(fileName, PATH_MAX);
1226 name_len++; /* trailing null */
1227 pSMB->NameLength = cpu_to_le16(name_len);
1228 strncpy(pSMB->fileName, fileName, name_len);
1230 if (*pOplock & REQ_OPLOCK)
1231 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1232 else if (*pOplock & REQ_BATCHOPLOCK) {
1233 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1235 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1236 pSMB->AllocationSize = 0;
1237 /* set file as system file if special file such
1238 as fifo and server expecting SFU style and
1239 no Unix extensions */
1240 if (create_options & CREATE_OPTION_SPECIAL)
1241 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1243 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1244 /* XP does not handle ATTR_POSIX_SEMANTICS */
1245 /* but it helps speed up case sensitive checks for other
1246 servers such as Samba */
1247 if (tcon->ses->capabilities & CAP_UNIX)
1248 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1250 /* if ((omode & S_IWUGO) == 0)
1251 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
1252 /* Above line causes problems due to vfs splitting create into two
1253 pieces - need to set mode after file created not while it is
1255 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1256 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1257 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1258 /* BB Expirement with various impersonation levels and verify */
1259 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1260 pSMB->SecurityFlags =
1261 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1264 pSMB->hdr.smb_buf_length += count;
1266 pSMB->ByteCount = cpu_to_le16(count);
1267 /* long_op set to 1 to allow for oplock break timeouts */
1268 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1269 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
1270 cifs_stats_inc(&tcon->num_opens);
1272 cFYI(1, ("Error in Open = %d", rc));
1274 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1275 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1276 /* Let caller know file was created so we can set the mode. */
1277 /* Do we care about the CreateAction in any other cases? */
1278 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1279 *pOplock |= CIFS_CREATE_ACTION;
1281 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1282 36 /* CreationTime to Attributes */);
1283 /* the file_info buf is endian converted by caller */
1284 pfile_info->AllocationSize = pSMBr->AllocationSize;
1285 pfile_info->EndOfFile = pSMBr->EndOfFile;
1286 pfile_info->NumberOfLinks = cpu_to_le32(1);
1290 cifs_buf_release(pSMB);
1297 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1298 const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1299 char **buf, int *pbuf_type)
1302 READ_REQ *pSMB = NULL;
1303 READ_RSP *pSMBr = NULL;
1304 char *pReadData = NULL;
1306 int resp_buf_type = 0;
1309 cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1310 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1313 wct = 10; /* old style read */
1316 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1320 /* tcon and ses pointer are checked in smb_init */
1321 if (tcon->ses->server == NULL)
1322 return -ECONNABORTED;
1324 pSMB->AndXCommand = 0xFF; /* none */
1326 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1328 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1329 else if ((lseek >> 32) > 0) /* can not handle this big offset for old */
1332 pSMB->Remaining = 0;
1333 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1334 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1336 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1338 /* old style read */
1339 struct smb_com_readx_req *pSMBW =
1340 (struct smb_com_readx_req *)pSMB;
1341 pSMBW->ByteCount = 0;
1344 iov[0].iov_base = (char *)pSMB;
1345 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1346 rc = SendReceive2(xid, tcon->ses, iov,
1349 cifs_stats_inc(&tcon->num_reads);
1350 pSMBr = (READ_RSP *)iov[0].iov_base;
1352 cERROR(1, ("Send error in read = %d", rc));
1354 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1355 data_length = data_length << 16;
1356 data_length += le16_to_cpu(pSMBr->DataLength);
1357 *nbytes = data_length;
1359 /*check that DataLength would not go beyond end of SMB */
1360 if ((data_length > CIFSMaxBufSize)
1361 || (data_length > count)) {
1362 cFYI(1, ("bad length %d for count %d",
1363 data_length, count));
1367 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1368 le16_to_cpu(pSMBr->DataOffset);
1369 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1370 cERROR(1,("Faulting on read rc = %d",rc));
1372 }*/ /* can not use copy_to_user when using page cache*/
1374 memcpy(*buf, pReadData, data_length);
1378 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1380 if (resp_buf_type == CIFS_SMALL_BUFFER)
1381 cifs_small_buf_release(iov[0].iov_base);
1382 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1383 cifs_buf_release(iov[0].iov_base);
1384 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1385 /* return buffer to caller to free */
1386 *buf = iov[0].iov_base;
1387 if (resp_buf_type == CIFS_SMALL_BUFFER)
1388 *pbuf_type = CIFS_SMALL_BUFFER;
1389 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1390 *pbuf_type = CIFS_LARGE_BUFFER;
1391 } /* else no valid buffer on return - leave as null */
1393 /* Note: On -EAGAIN error only caller can retry on handle based calls
1394 since file handle passed in no longer valid */
1400 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1401 const int netfid, const unsigned int count,
1402 const __u64 offset, unsigned int *nbytes, const char *buf,
1403 const char __user *ubuf, const int long_op)
1406 WRITE_REQ *pSMB = NULL;
1407 WRITE_RSP *pSMBr = NULL;
1408 int bytes_returned, wct;
1412 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1413 if (tcon->ses == NULL)
1414 return -ECONNABORTED;
1416 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1421 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1425 /* tcon and ses pointer are checked in smb_init */
1426 if (tcon->ses->server == NULL)
1427 return -ECONNABORTED;
1429 pSMB->AndXCommand = 0xFF; /* none */
1431 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1433 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1434 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1437 pSMB->Reserved = 0xFFFFFFFF;
1438 pSMB->WriteMode = 0;
1439 pSMB->Remaining = 0;
1441 /* Can increase buffer size if buffer is big enough in some cases ie we
1442 can send more if LARGE_WRITE_X capability returned by the server and if
1443 our buffer is big enough or if we convert to iovecs on socket writes
1444 and eliminate the copy to the CIFS buffer */
1445 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1446 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1448 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1452 if (bytes_sent > count)
1455 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1457 memcpy(pSMB->Data, buf, bytes_sent);
1459 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1460 cifs_buf_release(pSMB);
1463 } else if (count != 0) {
1465 cifs_buf_release(pSMB);
1467 } /* else setting file size with write of zero bytes */
1469 byte_count = bytes_sent + 1; /* pad */
1470 else /* wct == 12 */ {
1471 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1473 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1474 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1475 pSMB->hdr.smb_buf_length += byte_count;
1478 pSMB->ByteCount = cpu_to_le16(byte_count);
1479 else { /* old style write has byte count 4 bytes earlier
1481 struct smb_com_writex_req *pSMBW =
1482 (struct smb_com_writex_req *)pSMB;
1483 pSMBW->ByteCount = cpu_to_le16(byte_count);
1486 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1487 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1488 cifs_stats_inc(&tcon->num_writes);
1490 cFYI(1, ("Send error in write = %d", rc));
1493 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1494 *nbytes = (*nbytes) << 16;
1495 *nbytes += le16_to_cpu(pSMBr->Count);
1498 cifs_buf_release(pSMB);
1500 /* Note: On -EAGAIN error only caller can retry on handle based calls
1501 since file handle passed in no longer valid */
1507 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1508 const int netfid, const unsigned int count,
1509 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1510 int n_vec, const int long_op)
1513 WRITE_REQ *pSMB = NULL;
1516 int resp_buf_type = 0;
1518 cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1520 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1524 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1527 /* tcon and ses pointer are checked in smb_init */
1528 if (tcon->ses->server == NULL)
1529 return -ECONNABORTED;
1531 pSMB->AndXCommand = 0xFF; /* none */
1533 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1535 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1536 else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
1538 pSMB->Reserved = 0xFFFFFFFF;
1539 pSMB->WriteMode = 0;
1540 pSMB->Remaining = 0;
1543 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1545 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1546 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1547 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1549 pSMB->hdr.smb_buf_length += count+1;
1550 else /* wct == 12 */
1551 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1553 pSMB->ByteCount = cpu_to_le16(count + 1);
1554 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1555 struct smb_com_writex_req *pSMBW =
1556 (struct smb_com_writex_req *)pSMB;
1557 pSMBW->ByteCount = cpu_to_le16(count + 5);
1559 iov[0].iov_base = pSMB;
1561 iov[0].iov_len = smb_hdr_len + 4;
1562 else /* wct == 12 pad bigger by four bytes */
1563 iov[0].iov_len = smb_hdr_len + 8;
1566 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1568 cifs_stats_inc(&tcon->num_writes);
1570 cFYI(1, ("Send error Write2 = %d", rc));
1572 } else if (resp_buf_type == 0) {
1573 /* presumably this can not happen, but best to be safe */
1577 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1578 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1579 *nbytes = (*nbytes) << 16;
1580 *nbytes += le16_to_cpu(pSMBr->Count);
1583 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1584 if (resp_buf_type == CIFS_SMALL_BUFFER)
1585 cifs_small_buf_release(iov[0].iov_base);
1586 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1587 cifs_buf_release(iov[0].iov_base);
1589 /* Note: On -EAGAIN error only caller can retry on handle based calls
1590 since file handle passed in no longer valid */
1597 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1598 const __u16 smb_file_id, const __u64 len,
1599 const __u64 offset, const __u32 numUnlock,
1600 const __u32 numLock, const __u8 lockType, const int waitFlag)
1603 LOCK_REQ *pSMB = NULL;
1604 LOCK_RSP *pSMBr = NULL;
1609 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock));
1610 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1615 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1617 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1618 timeout = -1; /* no response expected */
1620 } else if (waitFlag == TRUE) {
1621 timeout = 3; /* blocking operation, no timeout */
1622 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1627 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1628 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1629 pSMB->LockType = lockType;
1630 pSMB->AndXCommand = 0xFF; /* none */
1631 pSMB->Fid = smb_file_id; /* netfid stays le */
1633 if ((numLock != 0) || (numUnlock != 0)) {
1634 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1635 /* BB where to store pid high? */
1636 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1637 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1638 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1639 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1640 count = sizeof(LOCKING_ANDX_RANGE);
1645 pSMB->hdr.smb_buf_length += count;
1646 pSMB->ByteCount = cpu_to_le16(count);
1649 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1650 (struct smb_hdr *) pSMBr, &bytes_returned);
1652 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1653 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1655 cifs_stats_inc(&tcon->num_locks);
1657 cFYI(1, ("Send error in Lock = %d", rc));
1659 cifs_small_buf_release(pSMB);
1661 /* Note: On -EAGAIN error only caller can retry on handle based calls
1662 since file handle passed in no longer valid */
1667 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1668 const __u16 smb_file_id, const int get_flag, const __u64 len,
1669 struct file_lock *pLockData, const __u16 lock_type,
1672 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1673 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1675 struct cifs_posix_lock *parm_data;
1678 int bytes_returned = 0;
1679 __u16 params, param_offset, offset, byte_count, count;
1681 cFYI(1, ("Posix Lock"));
1683 if (pLockData == NULL)
1686 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1691 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1694 pSMB->MaxSetupCount = 0;
1697 pSMB->Reserved2 = 0;
1698 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1699 offset = param_offset + params;
1701 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1703 count = sizeof(struct cifs_posix_lock);
1704 pSMB->MaxParameterCount = cpu_to_le16(2);
1705 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1706 pSMB->SetupCount = 1;
1707 pSMB->Reserved3 = 0;
1709 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1711 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1712 byte_count = 3 /* pad */ + params + count;
1713 pSMB->DataCount = cpu_to_le16(count);
1714 pSMB->ParameterCount = cpu_to_le16(params);
1715 pSMB->TotalDataCount = pSMB->DataCount;
1716 pSMB->TotalParameterCount = pSMB->ParameterCount;
1717 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1718 parm_data = (struct cifs_posix_lock *)
1719 (((char *) &pSMB->hdr.Protocol) + offset);
1721 parm_data->lock_type = cpu_to_le16(lock_type);
1723 timeout = 3; /* blocking operation, no timeout */
1724 parm_data->lock_flags = cpu_to_le16(1);
1725 pSMB->Timeout = cpu_to_le32(-1);
1729 parm_data->pid = cpu_to_le32(current->tgid);
1730 parm_data->start = cpu_to_le64(pLockData->fl_start);
1731 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
1733 pSMB->DataOffset = cpu_to_le16(offset);
1734 pSMB->Fid = smb_file_id;
1735 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1736 pSMB->Reserved4 = 0;
1737 pSMB->hdr.smb_buf_length += byte_count;
1738 pSMB->ByteCount = cpu_to_le16(byte_count);
1740 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1741 (struct smb_hdr *) pSMBr, &bytes_returned);
1743 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1744 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1748 cFYI(1, ("Send error in Posix Lock = %d", rc));
1749 } else if (get_flag) {
1750 /* lock structure can be returned on get */
1753 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1755 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1756 rc = -EIO; /* bad smb */
1759 if (pLockData == NULL) {
1763 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1764 data_count = le16_to_cpu(pSMBr->t2.DataCount);
1765 if (data_count < sizeof(struct cifs_posix_lock)) {
1769 parm_data = (struct cifs_posix_lock *)
1770 ((char *)&pSMBr->hdr.Protocol + data_offset);
1771 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1772 pLockData->fl_type = F_UNLCK;
1777 cifs_small_buf_release(pSMB);
1779 /* Note: On -EAGAIN error only caller can retry on handle based calls
1780 since file handle passed in no longer valid */
1787 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1790 CLOSE_REQ *pSMB = NULL;
1791 CLOSE_RSP *pSMBr = NULL;
1793 cFYI(1, ("In CIFSSMBClose"));
1795 /* do not retry on dead session on close */
1796 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1802 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1804 pSMB->FileID = (__u16) smb_file_id;
1805 pSMB->LastWriteTime = 0xFFFFFFFF;
1806 pSMB->ByteCount = 0;
1807 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1808 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1809 cifs_stats_inc(&tcon->num_closes);
1812 /* EINTR is expected when user ctl-c to kill app */
1813 cERROR(1, ("Send error in Close = %d", rc));
1817 cifs_small_buf_release(pSMB);
1819 /* Since session is dead, file will be closed on server already */
1827 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1828 const char *fromName, const char *toName,
1829 const struct nls_table *nls_codepage, int remap)
1832 RENAME_REQ *pSMB = NULL;
1833 RENAME_RSP *pSMBr = NULL;
1835 int name_len, name_len2;
1838 cFYI(1, ("In CIFSSMBRename"));
1840 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1845 pSMB->BufferFormat = 0x04;
1846 pSMB->SearchAttributes =
1847 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1850 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1852 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1853 PATH_MAX, nls_codepage, remap);
1854 name_len++; /* trailing null */
1856 pSMB->OldFileName[name_len] = 0x04; /* pad */
1857 /* protocol requires ASCII signature byte on Unicode string */
1858 pSMB->OldFileName[name_len + 1] = 0x00;
1860 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1861 toName, PATH_MAX, nls_codepage, remap);
1862 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1863 name_len2 *= 2; /* convert to bytes */
1864 } else { /* BB improve the check for buffer overruns BB */
1865 name_len = strnlen(fromName, PATH_MAX);
1866 name_len++; /* trailing null */
1867 strncpy(pSMB->OldFileName, fromName, name_len);
1868 name_len2 = strnlen(toName, PATH_MAX);
1869 name_len2++; /* trailing null */
1870 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1871 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1872 name_len2++; /* trailing null */
1873 name_len2++; /* signature byte */
1876 count = 1 /* 1st signature byte */ + name_len + name_len2;
1877 pSMB->hdr.smb_buf_length += count;
1878 pSMB->ByteCount = cpu_to_le16(count);
1880 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1881 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1882 cifs_stats_inc(&tcon->num_renames);
1884 cFYI(1, ("Send error in rename = %d", rc));
1887 cifs_buf_release(pSMB);
1895 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1896 int netfid, char *target_name,
1897 const struct nls_table *nls_codepage, int remap)
1899 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1900 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1901 struct set_file_rename *rename_info;
1903 char dummy_string[30];
1905 int bytes_returned = 0;
1907 __u16 params, param_offset, offset, count, byte_count;
1909 cFYI(1, ("Rename to File by handle"));
1910 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1916 pSMB->MaxSetupCount = 0;
1920 pSMB->Reserved2 = 0;
1921 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1922 offset = param_offset + params;
1924 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1925 rename_info = (struct set_file_rename *) data_offset;
1926 pSMB->MaxParameterCount = cpu_to_le16(2);
1927 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1928 pSMB->SetupCount = 1;
1929 pSMB->Reserved3 = 0;
1930 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1931 byte_count = 3 /* pad */ + params;
1932 pSMB->ParameterCount = cpu_to_le16(params);
1933 pSMB->TotalParameterCount = pSMB->ParameterCount;
1934 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1935 pSMB->DataOffset = cpu_to_le16(offset);
1936 /* construct random name ".cifs_tmp<inodenum><mid>" */
1937 rename_info->overwrite = cpu_to_le32(1);
1938 rename_info->root_fid = 0;
1939 /* unicode only call */
1940 if (target_name == NULL) {
1941 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
1942 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1943 dummy_string, 24, nls_codepage, remap);
1945 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1946 target_name, PATH_MAX, nls_codepage,
1949 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1950 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1951 byte_count += count;
1952 pSMB->DataCount = cpu_to_le16(count);
1953 pSMB->TotalDataCount = pSMB->DataCount;
1955 pSMB->InformationLevel =
1956 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1957 pSMB->Reserved4 = 0;
1958 pSMB->hdr.smb_buf_length += byte_count;
1959 pSMB->ByteCount = cpu_to_le16(byte_count);
1960 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1961 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1962 cifs_stats_inc(&pTcon->num_t2renames);
1964 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
1967 cifs_buf_release(pSMB);
1969 /* Note: On -EAGAIN error only caller can retry on handle based calls
1970 since file handle passed in no longer valid */
1976 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
1977 const __u16 target_tid, const char *toName, const int flags,
1978 const struct nls_table *nls_codepage, int remap)
1981 COPY_REQ *pSMB = NULL;
1982 COPY_RSP *pSMBr = NULL;
1984 int name_len, name_len2;
1987 cFYI(1, ("In CIFSSMBCopy"));
1989 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1994 pSMB->BufferFormat = 0x04;
1995 pSMB->Tid2 = target_tid;
1997 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1999 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2000 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2001 fromName, PATH_MAX, nls_codepage,
2003 name_len++; /* trailing null */
2005 pSMB->OldFileName[name_len] = 0x04; /* pad */
2006 /* protocol requires ASCII signature byte on Unicode string */
2007 pSMB->OldFileName[name_len + 1] = 0x00;
2009 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2010 toName, PATH_MAX, nls_codepage, remap);
2011 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2012 name_len2 *= 2; /* convert to bytes */
2013 } else { /* BB improve the check for buffer overruns BB */
2014 name_len = strnlen(fromName, PATH_MAX);
2015 name_len++; /* trailing null */
2016 strncpy(pSMB->OldFileName, fromName, name_len);
2017 name_len2 = strnlen(toName, PATH_MAX);
2018 name_len2++; /* trailing null */
2019 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2020 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2021 name_len2++; /* trailing null */
2022 name_len2++; /* signature byte */
2025 count = 1 /* 1st signature byte */ + name_len + name_len2;
2026 pSMB->hdr.smb_buf_length += count;
2027 pSMB->ByteCount = cpu_to_le16(count);
2029 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2030 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2032 cFYI(1, ("Send error in copy = %d with %d files copied",
2033 rc, le16_to_cpu(pSMBr->CopyCount)));
2036 cifs_buf_release(pSMB);
2045 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2046 const char *fromName, const char *toName,
2047 const struct nls_table *nls_codepage)
2049 TRANSACTION2_SPI_REQ *pSMB = NULL;
2050 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2053 int name_len_target;
2055 int bytes_returned = 0;
2056 __u16 params, param_offset, offset, byte_count;
2058 cFYI(1, ("In Symlink Unix style"));
2060 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2065 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2067 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2068 /* find define for this maxpathcomponent */
2070 name_len++; /* trailing null */
2073 } else { /* BB improve the check for buffer overruns BB */
2074 name_len = strnlen(fromName, PATH_MAX);
2075 name_len++; /* trailing null */
2076 strncpy(pSMB->FileName, fromName, name_len);
2078 params = 6 + name_len;
2079 pSMB->MaxSetupCount = 0;
2083 pSMB->Reserved2 = 0;
2084 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2085 InformationLevel) - 4;
2086 offset = param_offset + params;
2088 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2089 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2091 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2092 /* find define for this maxpathcomponent */
2094 name_len_target++; /* trailing null */
2095 name_len_target *= 2;
2096 } else { /* BB improve the check for buffer overruns BB */
2097 name_len_target = strnlen(toName, PATH_MAX);
2098 name_len_target++; /* trailing null */
2099 strncpy(data_offset, toName, name_len_target);
2102 pSMB->MaxParameterCount = cpu_to_le16(2);
2103 /* BB find exact max on data count below from sess */
2104 pSMB->MaxDataCount = cpu_to_le16(1000);
2105 pSMB->SetupCount = 1;
2106 pSMB->Reserved3 = 0;
2107 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2108 byte_count = 3 /* pad */ + params + name_len_target;
2109 pSMB->DataCount = cpu_to_le16(name_len_target);
2110 pSMB->ParameterCount = cpu_to_le16(params);
2111 pSMB->TotalDataCount = pSMB->DataCount;
2112 pSMB->TotalParameterCount = pSMB->ParameterCount;
2113 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2114 pSMB->DataOffset = cpu_to_le16(offset);
2115 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2116 pSMB->Reserved4 = 0;
2117 pSMB->hdr.smb_buf_length += byte_count;
2118 pSMB->ByteCount = cpu_to_le16(byte_count);
2119 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2120 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2121 cifs_stats_inc(&tcon->num_symlinks);
2124 ("Send error in SetPathInfo (create symlink) = %d",
2129 cifs_buf_release(pSMB);
2132 goto createSymLinkRetry;
2138 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2139 const char *fromName, const char *toName,
2140 const struct nls_table *nls_codepage, int remap)
2142 TRANSACTION2_SPI_REQ *pSMB = NULL;
2143 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2146 int name_len_target;
2148 int bytes_returned = 0;
2149 __u16 params, param_offset, offset, byte_count;
2151 cFYI(1, ("In Create Hard link Unix style"));
2152 createHardLinkRetry:
2153 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2158 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2159 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2160 PATH_MAX, nls_codepage, remap);
2161 name_len++; /* trailing null */
2164 } else { /* BB improve the check for buffer overruns BB */
2165 name_len = strnlen(toName, PATH_MAX);
2166 name_len++; /* trailing null */
2167 strncpy(pSMB->FileName, toName, name_len);
2169 params = 6 + name_len;
2170 pSMB->MaxSetupCount = 0;
2174 pSMB->Reserved2 = 0;
2175 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2176 InformationLevel) - 4;
2177 offset = param_offset + params;
2179 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2182 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2183 nls_codepage, remap);
2184 name_len_target++; /* trailing null */
2185 name_len_target *= 2;
2186 } else { /* BB improve the check for buffer overruns BB */
2187 name_len_target = strnlen(fromName, PATH_MAX);
2188 name_len_target++; /* trailing null */
2189 strncpy(data_offset, fromName, name_len_target);
2192 pSMB->MaxParameterCount = cpu_to_le16(2);
2193 /* BB find exact max on data count below from sess*/
2194 pSMB->MaxDataCount = cpu_to_le16(1000);
2195 pSMB->SetupCount = 1;
2196 pSMB->Reserved3 = 0;
2197 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2198 byte_count = 3 /* pad */ + params + name_len_target;
2199 pSMB->ParameterCount = cpu_to_le16(params);
2200 pSMB->TotalParameterCount = pSMB->ParameterCount;
2201 pSMB->DataCount = cpu_to_le16(name_len_target);
2202 pSMB->TotalDataCount = pSMB->DataCount;
2203 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2204 pSMB->DataOffset = cpu_to_le16(offset);
2205 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2206 pSMB->Reserved4 = 0;
2207 pSMB->hdr.smb_buf_length += byte_count;
2208 pSMB->ByteCount = cpu_to_le16(byte_count);
2209 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2210 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2211 cifs_stats_inc(&tcon->num_hardlinks);
2213 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2216 cifs_buf_release(pSMB);
2218 goto createHardLinkRetry;
2224 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2225 const char *fromName, const char *toName,
2226 const struct nls_table *nls_codepage, int remap)
2229 NT_RENAME_REQ *pSMB = NULL;
2230 RENAME_RSP *pSMBr = NULL;
2232 int name_len, name_len2;
2235 cFYI(1, ("In CIFSCreateHardLink"));
2236 winCreateHardLinkRetry:
2238 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2243 pSMB->SearchAttributes =
2244 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2246 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2247 pSMB->ClusterCount = 0;
2249 pSMB->BufferFormat = 0x04;
2251 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2253 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2254 PATH_MAX, nls_codepage, remap);
2255 name_len++; /* trailing null */
2257 pSMB->OldFileName[name_len] = 0; /* pad */
2258 pSMB->OldFileName[name_len + 1] = 0x04;
2260 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2261 toName, PATH_MAX, nls_codepage, remap);
2262 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2263 name_len2 *= 2; /* convert to bytes */
2264 } else { /* BB improve the check for buffer overruns BB */
2265 name_len = strnlen(fromName, PATH_MAX);
2266 name_len++; /* trailing null */
2267 strncpy(pSMB->OldFileName, fromName, name_len);
2268 name_len2 = strnlen(toName, PATH_MAX);
2269 name_len2++; /* trailing null */
2270 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2271 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2272 name_len2++; /* trailing null */
2273 name_len2++; /* signature byte */
2276 count = 1 /* string type byte */ + name_len + name_len2;
2277 pSMB->hdr.smb_buf_length += count;
2278 pSMB->ByteCount = cpu_to_le16(count);
2280 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2281 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2282 cifs_stats_inc(&tcon->num_hardlinks);
2284 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2286 cifs_buf_release(pSMB);
2288 goto winCreateHardLinkRetry;
2294 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2295 const unsigned char *searchName,
2296 char *symlinkinfo, const int buflen,
2297 const struct nls_table *nls_codepage)
2299 /* SMB_QUERY_FILE_UNIX_LINK */
2300 TRANSACTION2_QPI_REQ *pSMB = NULL;
2301 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2305 __u16 params, byte_count;
2307 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2310 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2315 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2317 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2318 PATH_MAX, nls_codepage);
2319 name_len++; /* trailing null */
2321 } else { /* BB improve the check for buffer overruns BB */
2322 name_len = strnlen(searchName, PATH_MAX);
2323 name_len++; /* trailing null */
2324 strncpy(pSMB->FileName, searchName, name_len);
2327 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2328 pSMB->TotalDataCount = 0;
2329 pSMB->MaxParameterCount = cpu_to_le16(2);
2330 /* BB find exact max data count below from sess structure BB */
2331 pSMB->MaxDataCount = cpu_to_le16(4000);
2332 pSMB->MaxSetupCount = 0;
2336 pSMB->Reserved2 = 0;
2337 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2338 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2339 pSMB->DataCount = 0;
2340 pSMB->DataOffset = 0;
2341 pSMB->SetupCount = 1;
2342 pSMB->Reserved3 = 0;
2343 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2344 byte_count = params + 1 /* pad */ ;
2345 pSMB->TotalParameterCount = cpu_to_le16(params);
2346 pSMB->ParameterCount = pSMB->TotalParameterCount;
2347 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2348 pSMB->Reserved4 = 0;
2349 pSMB->hdr.smb_buf_length += byte_count;
2350 pSMB->ByteCount = cpu_to_le16(byte_count);
2352 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2353 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2355 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2357 /* decode response */
2359 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2360 if (rc || (pSMBr->ByteCount < 2))
2361 /* BB also check enough total bytes returned */
2362 rc = -EIO; /* bad smb */
2364 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2365 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2367 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2368 name_len = UniStrnlen((wchar_t *) ((char *)
2369 &pSMBr->hdr.Protocol + data_offset),
2370 min_t(const int, buflen, count) / 2);
2371 /* BB FIXME investigate remapping reserved chars here */
2372 cifs_strfromUCS_le(symlinkinfo,
2373 (__le16 *) ((char *)&pSMBr->hdr.Protocol
2375 name_len, nls_codepage);
2377 strncpy(symlinkinfo,
2378 (char *) &pSMBr->hdr.Protocol +
2380 min_t(const int, buflen, count));
2382 symlinkinfo[buflen] = 0;
2383 /* just in case so calling code does not go off the end of buffer */
2386 cifs_buf_release(pSMB);
2388 goto querySymLinkRetry;
2392 /* Initialize NT TRANSACT SMB into small smb request buffer.
2393 This assumes that all NT TRANSACTS that we init here have
2394 total parm and data under about 400 bytes (to fit in small cifs
2395 buffer size), which is the case so far, it easily fits. NB:
2396 Setup words themselves and ByteCount
2397 MaxSetupCount (size of returned setup area) and
2398 MaxParameterCount (returned parms size) must be set by caller */
2400 smb_init_ntransact(const __u16 sub_command, const int setup_count,
2401 const int parm_len, struct cifsTconInfo *tcon,
2406 struct smb_com_ntransact_req *pSMB;
2408 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2412 *ret_buf = (void *)pSMB;
2414 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2415 pSMB->TotalDataCount = 0;
2416 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2417 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2418 pSMB->ParameterCount = pSMB->TotalParameterCount;
2419 pSMB->DataCount = pSMB->TotalDataCount;
2420 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2421 (setup_count * 2) - 4 /* for rfc1001 length itself */;
2422 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2423 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2424 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2425 pSMB->SubCommand = cpu_to_le16(sub_command);
2430 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2431 int *pdatalen, int *pparmlen)
2434 __u32 data_count, data_offset, parm_count, parm_offset;
2435 struct smb_com_ntransact_rsp *pSMBr;
2440 pSMBr = (struct smb_com_ntransact_rsp *)buf;
2442 /* ByteCount was converted from little endian in SendReceive */
2443 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2444 (char *)&pSMBr->ByteCount;
2446 data_offset = le32_to_cpu(pSMBr->DataOffset);
2447 data_count = le32_to_cpu(pSMBr->DataCount);
2448 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2449 parm_count = le32_to_cpu(pSMBr->ParameterCount);
2451 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2452 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2454 /* should we also check that parm and data areas do not overlap? */
2455 if (*ppparm > end_of_smb) {
2456 cFYI(1, ("parms start after end of smb"));
2458 } else if (parm_count + *ppparm > end_of_smb) {
2459 cFYI(1, ("parm end after end of smb"));
2461 } else if (*ppdata > end_of_smb) {
2462 cFYI(1, ("data starts after end of smb"));
2464 } else if (data_count + *ppdata > end_of_smb) {
2465 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2466 *ppdata, data_count, (data_count + *ppdata),
2467 end_of_smb, pSMBr));
2469 } else if (parm_count + data_count > pSMBr->ByteCount) {
2470 cFYI(1, ("parm count and data count larger than SMB"));
2477 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2478 const unsigned char *searchName,
2479 char *symlinkinfo, const int buflen, __u16 fid,
2480 const struct nls_table *nls_codepage)
2485 struct smb_com_transaction_ioctl_req *pSMB;
2486 struct smb_com_transaction_ioctl_rsp *pSMBr;
2488 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2489 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2494 pSMB->TotalParameterCount = 0 ;
2495 pSMB->TotalDataCount = 0;
2496 pSMB->MaxParameterCount = cpu_to_le32(2);
2497 /* BB find exact data count max from sess structure BB */
2498 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2499 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2500 pSMB->MaxSetupCount = 4;
2502 pSMB->ParameterOffset = 0;
2503 pSMB->DataCount = 0;
2504 pSMB->DataOffset = 0;
2505 pSMB->SetupCount = 4;
2506 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2507 pSMB->ParameterCount = pSMB->TotalParameterCount;
2508 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2509 pSMB->IsFsctl = 1; /* FSCTL */
2510 pSMB->IsRootFlag = 0;
2511 pSMB->Fid = fid; /* file handle always le */
2512 pSMB->ByteCount = 0;
2514 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2515 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2517 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2518 } else { /* decode response */
2519 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2520 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2521 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2522 /* BB also check enough total bytes returned */
2523 rc = -EIO; /* bad smb */
2525 if (data_count && (data_count < 2048)) {
2526 char *end_of_smb = 2 /* sizeof byte count */ +
2528 (char *)&pSMBr->ByteCount;
2530 struct reparse_data *reparse_buf =
2531 (struct reparse_data *)
2532 ((char *)&pSMBr->hdr.Protocol
2534 if ((char *)reparse_buf >= end_of_smb) {
2538 if ((reparse_buf->LinkNamesBuf +
2539 reparse_buf->TargetNameOffset +
2540 reparse_buf->TargetNameLen) >
2542 cFYI(1,("reparse buf extended beyond SMB"));
2547 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2548 name_len = UniStrnlen((wchar_t *)
2549 (reparse_buf->LinkNamesBuf +
2550 reparse_buf->TargetNameOffset),
2552 reparse_buf->TargetNameLen / 2));
2553 cifs_strfromUCS_le(symlinkinfo,
2554 (__le16 *) (reparse_buf->LinkNamesBuf +
2555 reparse_buf->TargetNameOffset),
2556 name_len, nls_codepage);
2557 } else { /* ASCII names */
2558 strncpy(symlinkinfo,
2559 reparse_buf->LinkNamesBuf +
2560 reparse_buf->TargetNameOffset,
2561 min_t(const int, buflen,
2562 reparse_buf->TargetNameLen));
2566 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2568 symlinkinfo[buflen] = 0; /* just in case so the caller
2569 does not go off the end of the buffer */
2570 cFYI(1, ("readlink result - %s", symlinkinfo));
2574 cifs_buf_release(pSMB);
2576 /* Note: On -EAGAIN error only caller can retry on handle based calls
2577 since file handle passed in no longer valid */
2582 #ifdef CONFIG_CIFS_POSIX
2584 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2585 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2586 struct cifs_posix_ace *cifs_ace)
2588 /* u8 cifs fields do not need le conversion */
2589 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2590 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2591 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2592 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2597 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2598 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2599 const int acl_type, const int size_of_data_area)
2604 struct cifs_posix_ace *pACE;
2605 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2606 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2608 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2611 if (acl_type & ACL_TYPE_ACCESS) {
2612 count = le16_to_cpu(cifs_acl->access_entry_count);
2613 pACE = &cifs_acl->ace_array[0];
2614 size = sizeof(struct cifs_posix_acl);
2615 size += sizeof(struct cifs_posix_ace) * count;
2616 /* check if we would go beyond end of SMB */
2617 if (size_of_data_area < size) {
2618 cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2619 size_of_data_area, size));
2622 } else if (acl_type & ACL_TYPE_DEFAULT) {
2623 count = le16_to_cpu(cifs_acl->access_entry_count);
2624 size = sizeof(struct cifs_posix_acl);
2625 size += sizeof(struct cifs_posix_ace) * count;
2626 /* skip past access ACEs to get to default ACEs */
2627 pACE = &cifs_acl->ace_array[count];
2628 count = le16_to_cpu(cifs_acl->default_entry_count);
2629 size += sizeof(struct cifs_posix_ace) * count;
2630 /* check if we would go beyond end of SMB */
2631 if (size_of_data_area < size)
2638 size = posix_acl_xattr_size(count);
2639 if ((buflen == 0) || (local_acl == NULL)) {
2640 /* used to query ACL EA size */
2641 } else if (size > buflen) {
2643 } else /* buffer big enough */ {
2644 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2645 for (i = 0; i < count ; i++) {
2646 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2653 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2654 const posix_acl_xattr_entry *local_ace)
2656 __u16 rc = 0; /* 0 = ACL converted ok */
2658 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2659 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2660 /* BB is there a better way to handle the large uid? */
2661 if (local_ace->e_id == cpu_to_le32(-1)) {
2662 /* Probably no need to le convert -1 on any arch but can not hurt */
2663 cifs_ace->cifs_uid = cpu_to_le64(-1);
2665 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2666 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2670 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2671 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2672 const int buflen, const int acl_type)
2675 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2676 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2680 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2683 count = posix_acl_xattr_count((size_t)buflen);
2684 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2685 count, buflen, le32_to_cpu(local_acl->a_version)));
2686 if (le32_to_cpu(local_acl->a_version) != 2) {
2687 cFYI(1, ("unknown POSIX ACL version %d",
2688 le32_to_cpu(local_acl->a_version)));
2691 cifs_acl->version = cpu_to_le16(1);
2692 if (acl_type == ACL_TYPE_ACCESS)
2693 cifs_acl->access_entry_count = cpu_to_le16(count);
2694 else if (acl_type == ACL_TYPE_DEFAULT)
2695 cifs_acl->default_entry_count = cpu_to_le16(count);
2697 cFYI(1, ("unknown ACL type %d", acl_type));
2700 for (i = 0; i < count; i++) {
2701 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2702 &local_acl->a_entries[i]);
2704 /* ACE not converted */
2709 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2710 rc += sizeof(struct cifs_posix_acl);
2711 /* BB add check to make sure ACL does not overflow SMB */
2717 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2718 const unsigned char *searchName,
2719 char *acl_inf, const int buflen, const int acl_type,
2720 const struct nls_table *nls_codepage, int remap)
2722 /* SMB_QUERY_POSIX_ACL */
2723 TRANSACTION2_QPI_REQ *pSMB = NULL;
2724 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2728 __u16 params, byte_count;
2730 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2733 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2738 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2740 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2741 PATH_MAX, nls_codepage, remap);
2742 name_len++; /* trailing null */
2744 pSMB->FileName[name_len] = 0;
2745 pSMB->FileName[name_len+1] = 0;
2746 } else { /* BB improve the check for buffer overruns BB */
2747 name_len = strnlen(searchName, PATH_MAX);
2748 name_len++; /* trailing null */
2749 strncpy(pSMB->FileName, searchName, name_len);
2752 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2753 pSMB->TotalDataCount = 0;
2754 pSMB->MaxParameterCount = cpu_to_le16(2);
2755 /* BB find exact max data count below from sess structure BB */
2756 pSMB->MaxDataCount = cpu_to_le16(4000);
2757 pSMB->MaxSetupCount = 0;
2761 pSMB->Reserved2 = 0;
2762 pSMB->ParameterOffset = cpu_to_le16(
2763 offsetof(struct smb_com_transaction2_qpi_req,
2764 InformationLevel) - 4);
2765 pSMB->DataCount = 0;
2766 pSMB->DataOffset = 0;
2767 pSMB->SetupCount = 1;
2768 pSMB->Reserved3 = 0;
2769 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2770 byte_count = params + 1 /* pad */ ;
2771 pSMB->TotalParameterCount = cpu_to_le16(params);
2772 pSMB->ParameterCount = pSMB->TotalParameterCount;
2773 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2774 pSMB->Reserved4 = 0;
2775 pSMB->hdr.smb_buf_length += byte_count;
2776 pSMB->ByteCount = cpu_to_le16(byte_count);
2778 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2779 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2780 cifs_stats_inc(&tcon->num_acl_get);
2782 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2784 /* decode response */
2786 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2787 if (rc || (pSMBr->ByteCount < 2))
2788 /* BB also check enough total bytes returned */
2789 rc = -EIO; /* bad smb */
2791 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2792 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2793 rc = cifs_copy_posix_acl(acl_inf,
2794 (char *)&pSMBr->hdr.Protocol+data_offset,
2795 buflen, acl_type, count);
2798 cifs_buf_release(pSMB);
2805 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2806 const unsigned char *fileName,
2807 const char *local_acl, const int buflen,
2809 const struct nls_table *nls_codepage, int remap)
2811 struct smb_com_transaction2_spi_req *pSMB = NULL;
2812 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2816 int bytes_returned = 0;
2817 __u16 params, byte_count, data_count, param_offset, offset;
2819 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2821 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2825 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2827 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2828 PATH_MAX, nls_codepage, remap);
2829 name_len++; /* trailing null */
2831 } else { /* BB improve the check for buffer overruns BB */
2832 name_len = strnlen(fileName, PATH_MAX);
2833 name_len++; /* trailing null */
2834 strncpy(pSMB->FileName, fileName, name_len);
2836 params = 6 + name_len;
2837 pSMB->MaxParameterCount = cpu_to_le16(2);
2838 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2839 pSMB->MaxSetupCount = 0;
2843 pSMB->Reserved2 = 0;
2844 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2845 InformationLevel) - 4;
2846 offset = param_offset + params;
2847 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2848 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2850 /* convert to on the wire format for POSIX ACL */
2851 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2853 if (data_count == 0) {
2855 goto setACLerrorExit;
2857 pSMB->DataOffset = cpu_to_le16(offset);
2858 pSMB->SetupCount = 1;
2859 pSMB->Reserved3 = 0;
2860 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2861 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2862 byte_count = 3 /* pad */ + params + data_count;
2863 pSMB->DataCount = cpu_to_le16(data_count);
2864 pSMB->TotalDataCount = pSMB->DataCount;
2865 pSMB->ParameterCount = cpu_to_le16(params);
2866 pSMB->TotalParameterCount = pSMB->ParameterCount;
2867 pSMB->Reserved4 = 0;
2868 pSMB->hdr.smb_buf_length += byte_count;
2869 pSMB->ByteCount = cpu_to_le16(byte_count);
2870 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2871 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2873 cFYI(1, ("Set POSIX ACL returned %d", rc));
2877 cifs_buf_release(pSMB);
2883 /* BB fix tabs in this function FIXME BB */
2885 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2886 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2889 struct smb_t2_qfi_req *pSMB = NULL;
2890 struct smb_t2_qfi_rsp *pSMBr = NULL;
2892 __u16 params, byte_count;
2894 cFYI(1, ("In GetExtAttr"));
2899 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2904 params = 2 /* level */ +2 /* fid */;
2905 pSMB->t2.TotalDataCount = 0;
2906 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2907 /* BB find exact max data count below from sess structure BB */
2908 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2909 pSMB->t2.MaxSetupCount = 0;
2910 pSMB->t2.Reserved = 0;
2912 pSMB->t2.Timeout = 0;
2913 pSMB->t2.Reserved2 = 0;
2914 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2916 pSMB->t2.DataCount = 0;
2917 pSMB->t2.DataOffset = 0;
2918 pSMB->t2.SetupCount = 1;
2919 pSMB->t2.Reserved3 = 0;
2920 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2921 byte_count = params + 1 /* pad */ ;
2922 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2923 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2924 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2927 pSMB->hdr.smb_buf_length += byte_count;
2928 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2933 cFYI(1, ("error %d in GetExtAttr", rc));
2935 /* decode response */
2936 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2937 if (rc || (pSMBr->ByteCount < 2))
2938 /* BB also check enough total bytes returned */
2939 /* If rc should we check for EOPNOSUPP and
2940 disable the srvino flag? or in caller? */
2941 rc = -EIO; /* bad smb */
2943 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2944 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2945 struct file_chattr_info *pfinfo;
2946 /* BB Do we need a cast or hash here ? */
2948 cFYI(1, ("Illegal size ret in GetExtAttr"));
2952 pfinfo = (struct file_chattr_info *)
2953 (data_offset + (char *) &pSMBr->hdr.Protocol);
2954 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2955 *pMask = le64_to_cpu(pfinfo->mask);
2959 cifs_buf_release(pSMB);
2961 goto GetExtAttrRetry;
2965 #endif /* CONFIG_POSIX */
2968 /* security id for everyone */
2969 static const struct cifs_sid sid_everyone =
2970 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2972 static const struct cifs_sid sid_user =
2973 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2975 /* Convert CIFS ACL to POSIX form */
2976 static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
2981 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2983 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2984 /* BB fix up return info */ char *acl_inf, const int buflen,
2985 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2989 QUERY_SEC_DESC_REQ * pSMB;
2992 cFYI(1, ("GetCifsACL"));
2994 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2995 8 /* parm len */, tcon, (void **) &pSMB);
2999 pSMB->MaxParameterCount = cpu_to_le32(4);
3000 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3001 pSMB->MaxSetupCount = 0;
3002 pSMB->Fid = fid; /* file handle always le */
3003 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3005 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3006 pSMB->hdr.smb_buf_length += 11;
3007 iov[0].iov_base = (char *)pSMB;
3008 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3010 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
3011 cifs_stats_inc(&tcon->num_acl_get);
3013 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3014 } else { /* decode response */
3015 struct cifs_sid *psec_desc;
3020 struct smb_com_ntransact_rsp *pSMBr;
3022 /* validate_nttransact */
3023 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3024 (char **)&psec_desc,
3025 &parm_len, &data_len);
3028 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3030 cERROR(1, ("smb %p parm %p data %p",
3031 pSMBr, parm, psec_desc)); /* BB removeme BB */
3033 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3034 rc = -EIO; /* bad smb */
3038 /* BB check that data area is minimum length and as big as acl_len */
3040 acl_len = le32_to_cpu(*(__le32 *)parm);
3041 /* BB check if (acl_len > bufsize) */
3043 parse_sec_desc(psec_desc, acl_len);
3046 if (buf_type == CIFS_SMALL_BUFFER)
3047 cifs_small_buf_release(iov[0].iov_base);
3048 else if (buf_type == CIFS_LARGE_BUFFER)
3049 cifs_buf_release(iov[0].iov_base);
3050 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3054 /* Legacy Query Path Information call for lookup to old servers such
3056 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3057 const unsigned char *searchName,
3058 FILE_ALL_INFO *pFinfo,
3059 const struct nls_table *nls_codepage, int remap)
3061 QUERY_INFORMATION_REQ * pSMB;
3062 QUERY_INFORMATION_RSP * pSMBr;
3067 cFYI(1, ("In SMBQPath path %s", searchName));
3069 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3074 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3076 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3077 PATH_MAX, nls_codepage, remap);
3078 name_len++; /* trailing null */
3081 name_len = strnlen(searchName, PATH_MAX);
3082 name_len++; /* trailing null */
3083 strncpy(pSMB->FileName, searchName, name_len);
3085 pSMB->BufferFormat = 0x04;
3086 name_len++; /* account for buffer type byte */
3087 pSMB->hdr.smb_buf_length += (__u16) name_len;
3088 pSMB->ByteCount = cpu_to_le16(name_len);
3090 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3093 cFYI(1, ("Send error in QueryInfo = %d", rc));
3094 } else if (pFinfo) { /* decode response */
3096 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3097 /* BB FIXME - add time zone adjustment BB */
3098 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3101 /* decode time fields */
3102 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3103 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3104 pFinfo->LastAccessTime = 0;
3105 pFinfo->AllocationSize =
3106 cpu_to_le64(le32_to_cpu(pSMBr->size));
3107 pFinfo->EndOfFile = pFinfo->AllocationSize;
3108 pFinfo->Attributes =
3109 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3111 rc = -EIO; /* bad buffer passed in */
3113 cifs_buf_release(pSMB);
3125 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3126 const unsigned char *searchName,
3127 FILE_ALL_INFO * pFindData,
3128 int legacy /* old style infolevel */,
3129 const struct nls_table *nls_codepage, int remap)
3131 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3132 TRANSACTION2_QPI_REQ *pSMB = NULL;
3133 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3137 __u16 params, byte_count;
3139 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3141 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3146 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3148 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3149 PATH_MAX, nls_codepage, remap);
3150 name_len++; /* trailing null */
3152 } else { /* BB improve the check for buffer overruns BB */
3153 name_len = strnlen(searchName, PATH_MAX);
3154 name_len++; /* trailing null */
3155 strncpy(pSMB->FileName, searchName, name_len);
3158 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3159 pSMB->TotalDataCount = 0;
3160 pSMB->MaxParameterCount = cpu_to_le16(2);
3161 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3162 pSMB->MaxSetupCount = 0;
3166 pSMB->Reserved2 = 0;
3167 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3168 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3169 pSMB->DataCount = 0;
3170 pSMB->DataOffset = 0;
3171 pSMB->SetupCount = 1;
3172 pSMB->Reserved3 = 0;
3173 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3174 byte_count = params + 1 /* pad */ ;
3175 pSMB->TotalParameterCount = cpu_to_le16(params);
3176 pSMB->ParameterCount = pSMB->TotalParameterCount;
3178 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3180 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3181 pSMB->Reserved4 = 0;
3182 pSMB->hdr.smb_buf_length += byte_count;
3183 pSMB->ByteCount = cpu_to_le16(byte_count);
3185 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3186 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3188 cFYI(1, ("Send error in QPathInfo = %d", rc));
3189 } else { /* decode response */
3190 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3192 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3194 else if (!legacy && (pSMBr->ByteCount < 40))
3195 rc = -EIO; /* bad smb */
3196 else if (legacy && (pSMBr->ByteCount < 24))
3197 rc = -EIO; /* 24 or 26 expected but we do not read
3199 else if (pFindData) {
3201 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3202 if (legacy) /* we do not read the last field, EAsize,
3203 fortunately since it varies by subdialect
3204 and on Set vs. Get, is two bytes or 4
3205 bytes depending but we don't care here */
3206 size = sizeof(FILE_INFO_STANDARD);
3208 size = sizeof(FILE_ALL_INFO);
3209 memcpy((char *) pFindData,
3210 (char *) &pSMBr->hdr.Protocol +
3215 cifs_buf_release(pSMB);
3217 goto QPathInfoRetry;
3223 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3224 const unsigned char *searchName,
3225 FILE_UNIX_BASIC_INFO * pFindData,
3226 const struct nls_table *nls_codepage, int remap)
3228 /* SMB_QUERY_FILE_UNIX_BASIC */
3229 TRANSACTION2_QPI_REQ *pSMB = NULL;
3230 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3232 int bytes_returned = 0;
3234 __u16 params, byte_count;
3236 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3238 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3243 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3245 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3246 PATH_MAX, nls_codepage, remap);
3247 name_len++; /* trailing null */
3249 } else { /* BB improve the check for buffer overruns BB */
3250 name_len = strnlen(searchName, PATH_MAX);
3251 name_len++; /* trailing null */
3252 strncpy(pSMB->FileName, searchName, name_len);
3255 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3256 pSMB->TotalDataCount = 0;
3257 pSMB->MaxParameterCount = cpu_to_le16(2);
3258 /* BB find exact max SMB PDU from sess structure BB */
3259 pSMB->MaxDataCount = cpu_to_le16(4000);
3260 pSMB->MaxSetupCount = 0;
3264 pSMB->Reserved2 = 0;
3265 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3266 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3267 pSMB->DataCount = 0;
3268 pSMB->DataOffset = 0;
3269 pSMB->SetupCount = 1;
3270 pSMB->Reserved3 = 0;
3271 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3272 byte_count = params + 1 /* pad */ ;
3273 pSMB->TotalParameterCount = cpu_to_le16(params);
3274 pSMB->ParameterCount = pSMB->TotalParameterCount;
3275 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3276 pSMB->Reserved4 = 0;
3277 pSMB->hdr.smb_buf_length += byte_count;
3278 pSMB->ByteCount = cpu_to_le16(byte_count);
3280 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3281 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3283 cFYI(1, ("Send error in QPathInfo = %d", rc));
3284 } else { /* decode response */
3285 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3287 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3288 rc = -EIO; /* bad smb */
3290 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3291 memcpy((char *) pFindData,
3292 (char *) &pSMBr->hdr.Protocol +
3294 sizeof (FILE_UNIX_BASIC_INFO));
3297 cifs_buf_release(pSMB);
3299 goto UnixQPathInfoRetry;
3304 #if 0 /* function unused at present */
3305 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
3306 const char *searchName, FILE_ALL_INFO * findData,
3307 const struct nls_table *nls_codepage)
3309 /* level 257 SMB_ */
3310 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3311 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3315 __u16 params, byte_count;
3317 cFYI(1, ("In FindUnique"));
3319 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3324 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3326 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3327 PATH_MAX, nls_codepage);
3328 name_len++; /* trailing null */
3330 } else { /* BB improve the check for buffer overruns BB */
3331 name_len = strnlen(searchName, PATH_MAX);
3332 name_len++; /* trailing null */
3333 strncpy(pSMB->FileName, searchName, name_len);
3336 params = 12 + name_len /* includes null */ ;
3337 pSMB->TotalDataCount = 0; /* no EAs */
3338 pSMB->MaxParameterCount = cpu_to_le16(2);
3339 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3340 pSMB->MaxSetupCount = 0;
3344 pSMB->Reserved2 = 0;
3345 pSMB->ParameterOffset = cpu_to_le16(
3346 offsetof(struct smb_com_transaction2_ffirst_req, InformationLevel)-4);
3347 pSMB->DataCount = 0;
3348 pSMB->DataOffset = 0;
3349 pSMB->SetupCount = 1; /* one byte, no need to le convert */
3350 pSMB->Reserved3 = 0;
3351 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3352 byte_count = params + 1 /* pad */ ;
3353 pSMB->TotalParameterCount = cpu_to_le16(params);
3354 pSMB->ParameterCount = pSMB->TotalParameterCount;
3355 pSMB->SearchAttributes =
3356 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3358 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
3359 pSMB->SearchFlags = cpu_to_le16(1);
3360 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3361 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
3362 pSMB->hdr.smb_buf_length += byte_count;
3363 pSMB->ByteCount = cpu_to_le16(byte_count);
3365 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3366 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3369 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
3370 } else { /* decode response */
3371 cifs_stats_inc(&tcon->num_ffirst);
3375 cifs_buf_release(pSMB);
3377 goto findUniqueRetry;
3381 #endif /* end unused (temporarily) function */
3383 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3385 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3386 const char *searchName,
3387 const struct nls_table *nls_codepage,
3389 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3391 /* level 257 SMB_ */
3392 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3393 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3394 T2_FFIRST_RSP_PARMS * parms;
3396 int bytes_returned = 0;
3398 __u16 params, byte_count;
3400 cFYI(1, ("In FindFirst for %s", searchName));
3403 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3408 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3410 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3411 PATH_MAX, nls_codepage, remap);
3412 /* We can not add the asterik earlier in case
3413 it got remapped to 0xF03A as if it were part of the
3414 directory name instead of a wildcard */
3416 pSMB->FileName[name_len] = dirsep;
3417 pSMB->FileName[name_len+1] = 0;
3418 pSMB->FileName[name_len+2] = '*';
3419 pSMB->FileName[name_len+3] = 0;
3420 name_len += 4; /* now the trailing null */
3421 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3422 pSMB->FileName[name_len+1] = 0;
3424 } else { /* BB add check for overrun of SMB buf BB */
3425 name_len = strnlen(searchName, PATH_MAX);
3426 /* BB fix here and in unicode clause above ie
3427 if (name_len > buffersize-header)
3428 free buffer exit; BB */
3429 strncpy(pSMB->FileName, searchName, name_len);
3430 pSMB->FileName[name_len] = dirsep;
3431 pSMB->FileName[name_len+1] = '*';
3432 pSMB->FileName[name_len+2] = 0;
3436 params = 12 + name_len /* includes null */ ;
3437 pSMB->TotalDataCount = 0; /* no EAs */
3438 pSMB->MaxParameterCount = cpu_to_le16(10);
3439 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3440 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3441 pSMB->MaxSetupCount = 0;
3445 pSMB->Reserved2 = 0;
3446 byte_count = params + 1 /* pad */ ;
3447 pSMB->TotalParameterCount = cpu_to_le16(params);
3448 pSMB->ParameterCount = pSMB->TotalParameterCount;
3449 pSMB->ParameterOffset = cpu_to_le16(
3450 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3452 pSMB->DataCount = 0;
3453 pSMB->DataOffset = 0;
3454 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3455 pSMB->Reserved3 = 0;
3456 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3457 pSMB->SearchAttributes =
3458 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3460 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3461 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3462 CIFS_SEARCH_RETURN_RESUME);
3463 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3465 /* BB what should we set StorageType to? Does it matter? BB */
3466 pSMB->SearchStorageType = 0;
3467 pSMB->hdr.smb_buf_length += byte_count;
3468 pSMB->ByteCount = cpu_to_le16(byte_count);
3470 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3471 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3472 cifs_stats_inc(&tcon->num_ffirst);
3474 if (rc) {/* BB add logic to retry regular search if Unix search
3475 rejected unexpectedly by server */
3476 /* BB Add code to handle unsupported level rc */
3477 cFYI(1, ("Error in FindFirst = %d", rc));
3479 cifs_buf_release(pSMB);
3481 /* BB eventually could optimize out free and realloc of buf */
3484 goto findFirstRetry;
3485 } else { /* decode response */
3486 /* BB remember to free buffer if error BB */
3487 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3489 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3490 psrch_inf->unicode = TRUE;
3492 psrch_inf->unicode = FALSE;
3494 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3495 psrch_inf->smallBuf = 0;
3496 psrch_inf->srch_entries_start =
3497 (char *) &pSMBr->hdr.Protocol +
3498 le16_to_cpu(pSMBr->t2.DataOffset);
3499 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3500 le16_to_cpu(pSMBr->t2.ParameterOffset));
3502 if (parms->EndofSearch)
3503 psrch_inf->endOfSearch = TRUE;
3505 psrch_inf->endOfSearch = FALSE;
3507 psrch_inf->entries_in_buffer =
3508 le16_to_cpu(parms->SearchCount);
3509 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3510 psrch_inf->entries_in_buffer;
3511 *pnetfid = parms->SearchHandle;
3513 cifs_buf_release(pSMB);
3520 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3521 __u16 searchHandle, struct cifs_search_info *psrch_inf)
3523 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3524 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3525 T2_FNEXT_RSP_PARMS * parms;
3526 char *response_data;
3528 int bytes_returned, name_len;
3529 __u16 params, byte_count;
3531 cFYI(1, ("In FindNext"));
3533 if (psrch_inf->endOfSearch == TRUE)
3536 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3541 params = 14; /* includes 2 bytes of null string, converted to LE below*/
3543 pSMB->TotalDataCount = 0; /* no EAs */
3544 pSMB->MaxParameterCount = cpu_to_le16(8);
3545 pSMB->MaxDataCount =
3546 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3548 pSMB->MaxSetupCount = 0;
3552 pSMB->Reserved2 = 0;
3553 pSMB->ParameterOffset = cpu_to_le16(
3554 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3555 pSMB->DataCount = 0;
3556 pSMB->DataOffset = 0;
3557 pSMB->SetupCount = 1;
3558 pSMB->Reserved3 = 0;
3559 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3560 pSMB->SearchHandle = searchHandle; /* always kept as le */
3562 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3563 /* test for Unix extensions */
3564 /* if (tcon->ses->capabilities & CAP_UNIX) {
3565 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3566 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3568 pSMB->InformationLevel =
3569 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3570 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3572 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3573 pSMB->ResumeKey = psrch_inf->resume_key;
3575 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3577 name_len = psrch_inf->resume_name_len;
3579 if (name_len < PATH_MAX) {
3580 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3581 byte_count += name_len;
3582 /* 14 byte parm len above enough for 2 byte null terminator */
3583 pSMB->ResumeFileName[name_len] = 0;
3584 pSMB->ResumeFileName[name_len+1] = 0;
3587 goto FNext2_err_exit;
3589 byte_count = params + 1 /* pad */ ;
3590 pSMB->TotalParameterCount = cpu_to_le16(params);
3591 pSMB->ParameterCount = pSMB->TotalParameterCount;
3592 pSMB->hdr.smb_buf_length += byte_count;
3593 pSMB->ByteCount = cpu_to_le16(byte_count);
3595 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3596 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3597 cifs_stats_inc(&tcon->num_fnext);
3600 psrch_inf->endOfSearch = TRUE;
3601 rc = 0; /* search probably was closed at end of search*/
3603 cFYI(1, ("FindNext returned = %d", rc));
3604 } else { /* decode response */
3605 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3608 /* BB fixme add lock for file (srch_info) struct here */
3609 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3610 psrch_inf->unicode = TRUE;
3612 psrch_inf->unicode = FALSE;
3613 response_data = (char *) &pSMBr->hdr.Protocol +
3614 le16_to_cpu(pSMBr->t2.ParameterOffset);
3615 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3616 response_data = (char *)&pSMBr->hdr.Protocol +
3617 le16_to_cpu(pSMBr->t2.DataOffset);
3618 if (psrch_inf->smallBuf)
3619 cifs_small_buf_release(
3620 psrch_inf->ntwrk_buf_start);
3622 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3623 psrch_inf->srch_entries_start = response_data;
3624 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3625 psrch_inf->smallBuf = 0;
3626 if (parms->EndofSearch)
3627 psrch_inf->endOfSearch = TRUE;
3629 psrch_inf->endOfSearch = FALSE;
3630 psrch_inf->entries_in_buffer =
3631 le16_to_cpu(parms->SearchCount);
3632 psrch_inf->index_of_last_entry +=
3633 psrch_inf->entries_in_buffer;
3634 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3635 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3637 /* BB fixme add unlock here */
3642 /* BB On error, should we leave previous search buf (and count and
3643 last entry fields) intact or free the previous one? */
3645 /* Note: On -EAGAIN error only caller can retry on handle based calls
3646 since file handle passed in no longer valid */
3649 cifs_buf_release(pSMB);
3654 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3655 const __u16 searchHandle)
3658 FINDCLOSE_REQ *pSMB = NULL;
3659 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3662 cFYI(1, ("In CIFSSMBFindClose"));
3663 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3665 /* no sense returning error if session restarted
3666 as file handle has been closed */
3672 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3673 pSMB->FileID = searchHandle;
3674 pSMB->ByteCount = 0;
3675 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3676 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3678 cERROR(1, ("Send error in FindClose = %d", rc));
3680 cifs_stats_inc(&tcon->num_fclose);
3681 cifs_small_buf_release(pSMB);
3683 /* Since session is dead, search handle closed on server already */
3691 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3692 const unsigned char *searchName,
3693 __u64 * inode_number,
3694 const struct nls_table *nls_codepage, int remap)
3697 TRANSACTION2_QPI_REQ *pSMB = NULL;
3698 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3699 int name_len, bytes_returned;
3700 __u16 params, byte_count;
3702 cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3706 GetInodeNumberRetry:
3707 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3712 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3714 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3715 PATH_MAX, nls_codepage, remap);
3716 name_len++; /* trailing null */
3718 } else { /* BB improve the check for buffer overruns BB */
3719 name_len = strnlen(searchName, PATH_MAX);
3720 name_len++; /* trailing null */
3721 strncpy(pSMB->FileName, searchName, name_len);
3724 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3725 pSMB->TotalDataCount = 0;
3726 pSMB->MaxParameterCount = cpu_to_le16(2);
3727 /* BB find exact max data count below from sess structure BB */
3728 pSMB->MaxDataCount = cpu_to_le16(4000);
3729 pSMB->MaxSetupCount = 0;
3733 pSMB->Reserved2 = 0;
3734 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3735 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3736 pSMB->DataCount = 0;
3737 pSMB->DataOffset = 0;
3738 pSMB->SetupCount = 1;
3739 pSMB->Reserved3 = 0;
3740 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3741 byte_count = params + 1 /* pad */ ;
3742 pSMB->TotalParameterCount = cpu_to_le16(params);
3743 pSMB->ParameterCount = pSMB->TotalParameterCount;
3744 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3745 pSMB->Reserved4 = 0;
3746 pSMB->hdr.smb_buf_length += byte_count;
3747 pSMB->ByteCount = cpu_to_le16(byte_count);
3749 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3750 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3752 cFYI(1, ("error %d in QueryInternalInfo", rc));
3754 /* decode response */
3755 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3756 if (rc || (pSMBr->ByteCount < 2))
3757 /* BB also check enough total bytes returned */
3758 /* If rc should we check for EOPNOSUPP and
3759 disable the srvino flag? or in caller? */
3760 rc = -EIO; /* bad smb */
3762 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3763 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3764 struct file_internal_info *pfinfo;
3765 /* BB Do we need a cast or hash here ? */
3767 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3769 goto GetInodeNumOut;
3771 pfinfo = (struct file_internal_info *)
3772 (data_offset + (char *) &pSMBr->hdr.Protocol);
3773 *inode_number = pfinfo->UniqueId;
3777 cifs_buf_release(pSMB);
3779 goto GetInodeNumberRetry;
3784 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3785 const unsigned char *searchName,
3786 unsigned char **targetUNCs,
3787 unsigned int *number_of_UNC_in_array,
3788 const struct nls_table *nls_codepage, int remap)
3790 /* TRANS2_GET_DFS_REFERRAL */
3791 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3792 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3793 struct dfs_referral_level_3 *referrals = NULL;
3799 __u16 params, byte_count;
3800 *number_of_UNC_in_array = 0;
3803 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3807 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3812 /* server pointer checked in called function,
3813 but should never be null here anyway */
3814 pSMB->hdr.Mid = GetNextMid(ses->server);
3815 pSMB->hdr.Tid = ses->ipc_tid;
3816 pSMB->hdr.Uid = ses->Suid;
3817 if (ses->capabilities & CAP_STATUS32) {
3818 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3820 if (ses->capabilities & CAP_DFS) {
3821 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3824 if (ses->capabilities & CAP_UNICODE) {
3825 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3827 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3828 searchName, PATH_MAX, nls_codepage, remap);
3829 name_len++; /* trailing null */
3831 } else { /* BB improve the check for buffer overruns BB */
3832 name_len = strnlen(searchName, PATH_MAX);
3833 name_len++; /* trailing null */
3834 strncpy(pSMB->RequestFileName, searchName, name_len);
3838 if (ses->server->secMode &
3839 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3840 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3843 pSMB->hdr.Uid = ses->Suid;
3845 params = 2 /* level */ + name_len /*includes null */ ;
3846 pSMB->TotalDataCount = 0;
3847 pSMB->DataCount = 0;
3848 pSMB->DataOffset = 0;
3849 pSMB->MaxParameterCount = 0;
3850 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3851 pSMB->MaxSetupCount = 0;
3855 pSMB->Reserved2 = 0;
3856 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3857 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3858 pSMB->SetupCount = 1;
3859 pSMB->Reserved3 = 0;
3860 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3861 byte_count = params + 3 /* pad */ ;
3862 pSMB->ParameterCount = cpu_to_le16(params);
3863 pSMB->TotalParameterCount = pSMB->ParameterCount;
3864 pSMB->MaxReferralLevel = cpu_to_le16(3);
3865 pSMB->hdr.smb_buf_length += byte_count;
3866 pSMB->ByteCount = cpu_to_le16(byte_count);
3868 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3869 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3871 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3872 } else { /* decode response */
3873 /* BB Add logic to parse referrals here */
3874 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3876 /* BB Also check if enough total bytes returned? */
3877 if (rc || (pSMBr->ByteCount < 17))
3878 rc = -EIO; /* bad smb */
3880 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3881 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3884 ("Decoding GetDFSRefer response BCC: %d Offset %d",
3885 pSMBr->ByteCount, data_offset));
3887 (struct dfs_referral_level_3 *)
3888 (8 /* sizeof start of data block */ +
3890 (char *) &pSMBr->hdr.Protocol);
3891 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",
3892 le16_to_cpu(pSMBr->NumberOfReferrals),
3893 le16_to_cpu(pSMBr->DFSFlags),
3894 le16_to_cpu(referrals->ReferralSize),
3895 le16_to_cpu(referrals->ServerType),
3896 le16_to_cpu(referrals->ReferralFlags),
3897 le16_to_cpu(referrals->TimeToLive)));
3898 /* BB This field is actually two bytes in from start of
3899 data block so we could do safety check that DataBlock
3900 begins at address of pSMBr->NumberOfReferrals */
3901 *number_of_UNC_in_array =
3902 le16_to_cpu(pSMBr->NumberOfReferrals);
3904 /* BB Fix below so can return more than one referral */
3905 if (*number_of_UNC_in_array > 1)
3906 *number_of_UNC_in_array = 1;
3908 /* get the length of the strings describing refs */
3910 for (i = 0; i < *number_of_UNC_in_array; i++) {
3911 /* make sure that DfsPathOffset not past end */
3913 le16_to_cpu(referrals->DfsPathOffset);
3914 if (offset > data_count) {
3915 /* if invalid referral, stop here and do
3916 not try to copy any more */
3917 *number_of_UNC_in_array = i;
3920 temp = ((char *)referrals) + offset;
3922 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3923 name_len += UniStrnlen((wchar_t *)temp,
3926 name_len += strnlen(temp, data_count);
3929 /* BB add check that referral pointer does
3930 not fall off end PDU */
3932 /* BB add check for name_len bigger than bcc */
3934 kmalloc(name_len+1+(*number_of_UNC_in_array),
3936 if (*targetUNCs == NULL) {
3940 /* copy the ref strings */
3941 referrals = (struct dfs_referral_level_3 *)
3942 (8 /* sizeof data hdr */ + data_offset +
3943 (char *) &pSMBr->hdr.Protocol);
3945 for (i = 0; i < *number_of_UNC_in_array; i++) {
3946 temp = ((char *)referrals) +
3947 le16_to_cpu(referrals->DfsPathOffset);
3948 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3949 cifs_strfromUCS_le(*targetUNCs,
3954 strncpy(*targetUNCs, temp, name_len);
3956 /* BB update target_uncs pointers */
3966 cifs_buf_release(pSMB);
3974 /* Query File System Info such as free space to old servers such as Win 9x */
3976 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3978 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3979 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3980 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3981 FILE_SYSTEM_ALLOC_INFO *response_data;
3983 int bytes_returned = 0;
3984 __u16 params, byte_count;
3986 cFYI(1, ("OldQFSInfo"));
3988 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3992 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3997 params = 2; /* level */
3998 pSMB->TotalDataCount = 0;
3999 pSMB->MaxParameterCount = cpu_to_le16(2);
4000 pSMB->MaxDataCount = cpu_to_le16(1000);
4001 pSMB->MaxSetupCount = 0;
4005 pSMB->Reserved2 = 0;
4006 byte_count = params + 1 /* pad */ ;
4007 pSMB->TotalParameterCount = cpu_to_le16(params);
4008 pSMB->ParameterCount = pSMB->TotalParameterCount;
4009 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4010 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4011 pSMB->DataCount = 0;
4012 pSMB->DataOffset = 0;
4013 pSMB->SetupCount = 1;
4014 pSMB->Reserved3 = 0;
4015 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4016 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4017 pSMB->hdr.smb_buf_length += byte_count;
4018 pSMB->ByteCount = cpu_to_le16(byte_count);
4020 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4021 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4023 cFYI(1, ("Send error in QFSInfo = %d", rc));
4024 } else { /* decode response */
4025 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4027 if (rc || (pSMBr->ByteCount < 18))
4028 rc = -EIO; /* bad smb */
4030 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4031 cFYI(1, ("qfsinf resp BCC: %d Offset %d",
4032 pSMBr->ByteCount, data_offset));
4034 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4035 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4037 le16_to_cpu(response_data->BytesPerSector) *
4038 le32_to_cpu(response_data->
4039 SectorsPerAllocationUnit);
4041 le32_to_cpu(response_data->TotalAllocationUnits);
4042 FSData->f_bfree = FSData->f_bavail =
4043 le32_to_cpu(response_data->FreeAllocationUnits);
4045 ("Blocks: %lld Free: %lld Block size %ld",
4046 (unsigned long long)FSData->f_blocks,
4047 (unsigned long long)FSData->f_bfree,
4051 cifs_buf_release(pSMB);
4054 goto oldQFSInfoRetry;
4060 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4062 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4063 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4064 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4065 FILE_SYSTEM_INFO *response_data;
4067 int bytes_returned = 0;
4068 __u16 params, byte_count;
4070 cFYI(1, ("In QFSInfo"));
4072 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4077 params = 2; /* level */
4078 pSMB->TotalDataCount = 0;
4079 pSMB->MaxParameterCount = cpu_to_le16(2);
4080 pSMB->MaxDataCount = cpu_to_le16(1000);
4081 pSMB->MaxSetupCount = 0;
4085 pSMB->Reserved2 = 0;
4086 byte_count = params + 1 /* pad */ ;
4087 pSMB->TotalParameterCount = cpu_to_le16(params);
4088 pSMB->ParameterCount = pSMB->TotalParameterCount;
4089 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4090 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4091 pSMB->DataCount = 0;
4092 pSMB->DataOffset = 0;
4093 pSMB->SetupCount = 1;
4094 pSMB->Reserved3 = 0;
4095 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4096 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4097 pSMB->hdr.smb_buf_length += byte_count;
4098 pSMB->ByteCount = cpu_to_le16(byte_count);
4100 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4101 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4103 cFYI(1, ("Send error in QFSInfo = %d", rc));
4104 } else { /* decode response */
4105 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4107 if (rc || (pSMBr->ByteCount < 24))
4108 rc = -EIO; /* bad smb */
4110 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4114 *) (((char *) &pSMBr->hdr.Protocol) +
4117 le32_to_cpu(response_data->BytesPerSector) *
4118 le32_to_cpu(response_data->
4119 SectorsPerAllocationUnit);
4121 le64_to_cpu(response_data->TotalAllocationUnits);
4122 FSData->f_bfree = FSData->f_bavail =
4123 le64_to_cpu(response_data->FreeAllocationUnits);
4125 ("Blocks: %lld Free: %lld Block size %ld",
4126 (unsigned long long)FSData->f_blocks,
4127 (unsigned long long)FSData->f_bfree,
4131 cifs_buf_release(pSMB);
4140 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4142 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4143 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4144 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4145 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4147 int bytes_returned = 0;
4148 __u16 params, byte_count;
4150 cFYI(1, ("In QFSAttributeInfo"));
4152 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4157 params = 2; /* level */
4158 pSMB->TotalDataCount = 0;
4159 pSMB->MaxParameterCount = cpu_to_le16(2);
4160 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4161 pSMB->MaxSetupCount = 0;
4165 pSMB->Reserved2 = 0;
4166 byte_count = params + 1 /* pad */ ;
4167 pSMB->TotalParameterCount = cpu_to_le16(params);
4168 pSMB->ParameterCount = pSMB->TotalParameterCount;
4169 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4170 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4171 pSMB->DataCount = 0;
4172 pSMB->DataOffset = 0;
4173 pSMB->SetupCount = 1;
4174 pSMB->Reserved3 = 0;
4175 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4176 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4177 pSMB->hdr.smb_buf_length += byte_count;
4178 pSMB->ByteCount = cpu_to_le16(byte_count);
4180 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4181 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4183 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4184 } else { /* decode response */
4185 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4187 if (rc || (pSMBr->ByteCount < 13)) {
4188 /* BB also check if enough bytes returned */
4189 rc = -EIO; /* bad smb */
4191 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4193 (FILE_SYSTEM_ATTRIBUTE_INFO
4194 *) (((char *) &pSMBr->hdr.Protocol) +
4196 memcpy(&tcon->fsAttrInfo, response_data,
4197 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
4200 cifs_buf_release(pSMB);
4203 goto QFSAttributeRetry;
4209 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4211 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4212 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4213 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4214 FILE_SYSTEM_DEVICE_INFO *response_data;
4216 int bytes_returned = 0;
4217 __u16 params, byte_count;
4219 cFYI(1, ("In QFSDeviceInfo"));
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);
4241 pSMB->DataCount = 0;
4242 pSMB->DataOffset = 0;
4243 pSMB->SetupCount = 1;
4244 pSMB->Reserved3 = 0;
4245 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4246 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4247 pSMB->hdr.smb_buf_length += byte_count;
4248 pSMB->ByteCount = cpu_to_le16(byte_count);
4250 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4251 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4253 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4254 } else { /* decode response */
4255 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4257 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
4258 rc = -EIO; /* bad smb */
4260 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4262 (FILE_SYSTEM_DEVICE_INFO *)
4263 (((char *) &pSMBr->hdr.Protocol) +
4265 memcpy(&tcon->fsDevInfo, response_data,
4266 sizeof (FILE_SYSTEM_DEVICE_INFO));
4269 cifs_buf_release(pSMB);
4272 goto QFSDeviceRetry;
4278 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4280 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4281 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4282 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4283 FILE_SYSTEM_UNIX_INFO *response_data;
4285 int bytes_returned = 0;
4286 __u16 params, byte_count;
4288 cFYI(1, ("In QFSUnixInfo"));
4290 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4295 params = 2; /* level */
4296 pSMB->TotalDataCount = 0;
4297 pSMB->DataCount = 0;
4298 pSMB->DataOffset = 0;
4299 pSMB->MaxParameterCount = cpu_to_le16(2);
4300 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4301 pSMB->MaxSetupCount = 0;
4305 pSMB->Reserved2 = 0;
4306 byte_count = params + 1 /* pad */ ;
4307 pSMB->ParameterCount = cpu_to_le16(params);
4308 pSMB->TotalParameterCount = pSMB->ParameterCount;
4309 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4310 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4311 pSMB->SetupCount = 1;
4312 pSMB->Reserved3 = 0;
4313 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4314 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4315 pSMB->hdr.smb_buf_length += byte_count;
4316 pSMB->ByteCount = cpu_to_le16(byte_count);
4318 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4319 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4321 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4322 } else { /* decode response */
4323 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4325 if (rc || (pSMBr->ByteCount < 13)) {
4326 rc = -EIO; /* bad smb */
4328 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4330 (FILE_SYSTEM_UNIX_INFO
4331 *) (((char *) &pSMBr->hdr.Protocol) +
4333 memcpy(&tcon->fsUnixInfo, response_data,
4334 sizeof (FILE_SYSTEM_UNIX_INFO));
4337 cifs_buf_release(pSMB);
4347 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4349 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4350 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4351 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4353 int bytes_returned = 0;
4354 __u16 params, param_offset, offset, byte_count;
4356 cFYI(1, ("In SETFSUnixInfo"));
4358 /* BB switch to small buf init to save memory */
4359 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4364 params = 4; /* 2 bytes zero followed by info level. */
4365 pSMB->MaxSetupCount = 0;
4369 pSMB->Reserved2 = 0;
4370 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4372 offset = param_offset + params;
4374 pSMB->MaxParameterCount = cpu_to_le16(4);
4375 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4376 pSMB->SetupCount = 1;
4377 pSMB->Reserved3 = 0;
4378 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4379 byte_count = 1 /* pad */ + params + 12;
4381 pSMB->DataCount = cpu_to_le16(12);
4382 pSMB->ParameterCount = cpu_to_le16(params);
4383 pSMB->TotalDataCount = pSMB->DataCount;
4384 pSMB->TotalParameterCount = pSMB->ParameterCount;
4385 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4386 pSMB->DataOffset = cpu_to_le16(offset);
4390 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4393 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4394 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4395 pSMB->ClientUnixCap = cpu_to_le64(cap);
4397 pSMB->hdr.smb_buf_length += byte_count;
4398 pSMB->ByteCount = cpu_to_le16(byte_count);
4400 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4401 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4403 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4404 } else { /* decode response */
4405 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4407 rc = -EIO; /* bad smb */
4410 cifs_buf_release(pSMB);
4413 goto SETFSUnixRetry;
4421 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4422 struct kstatfs *FSData)
4424 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
4425 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4426 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4427 FILE_SYSTEM_POSIX_INFO *response_data;
4429 int bytes_returned = 0;
4430 __u16 params, byte_count;
4432 cFYI(1, ("In QFSPosixInfo"));
4434 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4439 params = 2; /* level */
4440 pSMB->TotalDataCount = 0;
4441 pSMB->DataCount = 0;
4442 pSMB->DataOffset = 0;
4443 pSMB->MaxParameterCount = cpu_to_le16(2);
4444 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
4445 pSMB->MaxSetupCount = 0;
4449 pSMB->Reserved2 = 0;
4450 byte_count = params + 1 /* pad */ ;
4451 pSMB->ParameterCount = cpu_to_le16(params);
4452 pSMB->TotalParameterCount = pSMB->ParameterCount;
4453 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4454 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4455 pSMB->SetupCount = 1;
4456 pSMB->Reserved3 = 0;
4457 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4458 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4459 pSMB->hdr.smb_buf_length += byte_count;
4460 pSMB->ByteCount = cpu_to_le16(byte_count);
4462 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4463 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4465 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4466 } else { /* decode response */
4467 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4469 if (rc || (pSMBr->ByteCount < 13)) {
4470 rc = -EIO; /* bad smb */
4472 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4474 (FILE_SYSTEM_POSIX_INFO
4475 *) (((char *) &pSMBr->hdr.Protocol) +
4478 le32_to_cpu(response_data->BlockSize);
4480 le64_to_cpu(response_data->TotalBlocks);
4482 le64_to_cpu(response_data->BlocksAvail);
4483 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4484 FSData->f_bavail = FSData->f_bfree;
4487 le64_to_cpu(response_data->UserBlocksAvail);
4489 if (response_data->TotalFileNodes != cpu_to_le64(-1))
4491 le64_to_cpu(response_data->TotalFileNodes);
4492 if (response_data->FreeFileNodes != cpu_to_le64(-1))
4494 le64_to_cpu(response_data->FreeFileNodes);
4497 cifs_buf_release(pSMB);
4506 /* We can not use write of zero bytes trick to
4507 set file size due to need for large file support. Also note that
4508 this SetPathInfo is preferred to SetFileInfo based method in next
4509 routine which is only needed to work around a sharing violation bug
4510 in Samba which this routine can run into */
4513 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4514 __u64 size, int SetAllocation,
4515 const struct nls_table *nls_codepage, int remap)
4517 struct smb_com_transaction2_spi_req *pSMB = NULL;
4518 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4519 struct file_end_of_file_info *parm_data;
4522 int bytes_returned = 0;
4523 __u16 params, byte_count, data_count, param_offset, offset;
4525 cFYI(1, ("In SetEOF"));
4527 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4532 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4534 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4535 PATH_MAX, nls_codepage, remap);
4536 name_len++; /* trailing null */
4538 } else { /* BB improve the check for buffer overruns BB */
4539 name_len = strnlen(fileName, PATH_MAX);
4540 name_len++; /* trailing null */
4541 strncpy(pSMB->FileName, fileName, name_len);
4543 params = 6 + name_len;
4544 data_count = sizeof (struct file_end_of_file_info);
4545 pSMB->MaxParameterCount = cpu_to_le16(2);
4546 pSMB->MaxDataCount = cpu_to_le16(4100);
4547 pSMB->MaxSetupCount = 0;
4551 pSMB->Reserved2 = 0;
4552 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4553 InformationLevel) - 4;
4554 offset = param_offset + params;
4555 if (SetAllocation) {
4556 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4557 pSMB->InformationLevel =
4558 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4560 pSMB->InformationLevel =
4561 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4562 } else /* Set File Size */ {
4563 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4564 pSMB->InformationLevel =
4565 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4567 pSMB->InformationLevel =
4568 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4572 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4574 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4575 pSMB->DataOffset = cpu_to_le16(offset);
4576 pSMB->SetupCount = 1;
4577 pSMB->Reserved3 = 0;
4578 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4579 byte_count = 3 /* pad */ + params + data_count;
4580 pSMB->DataCount = cpu_to_le16(data_count);
4581 pSMB->TotalDataCount = pSMB->DataCount;
4582 pSMB->ParameterCount = cpu_to_le16(params);
4583 pSMB->TotalParameterCount = pSMB->ParameterCount;
4584 pSMB->Reserved4 = 0;
4585 pSMB->hdr.smb_buf_length += byte_count;
4586 parm_data->FileSize = cpu_to_le64(size);
4587 pSMB->ByteCount = cpu_to_le16(byte_count);
4588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4589 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4591 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4594 cifs_buf_release(pSMB);
4603 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4604 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4606 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4607 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4609 struct file_end_of_file_info *parm_data;
4611 int bytes_returned = 0;
4612 __u16 params, param_offset, offset, byte_count, count;
4614 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4616 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4621 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4623 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4624 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4627 pSMB->MaxSetupCount = 0;
4631 pSMB->Reserved2 = 0;
4632 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4633 offset = param_offset + params;
4635 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4637 count = sizeof(struct file_end_of_file_info);
4638 pSMB->MaxParameterCount = cpu_to_le16(2);
4639 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4640 pSMB->SetupCount = 1;
4641 pSMB->Reserved3 = 0;
4642 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4643 byte_count = 3 /* pad */ + params + count;
4644 pSMB->DataCount = cpu_to_le16(count);
4645 pSMB->ParameterCount = cpu_to_le16(params);
4646 pSMB->TotalDataCount = pSMB->DataCount;
4647 pSMB->TotalParameterCount = pSMB->ParameterCount;
4648 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4650 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4652 pSMB->DataOffset = cpu_to_le16(offset);
4653 parm_data->FileSize = cpu_to_le64(size);
4655 if (SetAllocation) {
4656 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4657 pSMB->InformationLevel =
4658 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4660 pSMB->InformationLevel =
4661 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4662 } else /* Set File Size */ {
4663 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4664 pSMB->InformationLevel =
4665 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4667 pSMB->InformationLevel =
4668 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4670 pSMB->Reserved4 = 0;
4671 pSMB->hdr.smb_buf_length += byte_count;
4672 pSMB->ByteCount = cpu_to_le16(byte_count);
4673 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4674 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4677 ("Send error in SetFileInfo (SetFileSize) = %d",
4682 cifs_small_buf_release(pSMB);
4684 /* Note: On -EAGAIN error only caller can retry on handle based calls
4685 since file handle passed in no longer valid */
4690 /* Some legacy servers such as NT4 require that the file times be set on
4691 an open handle, rather than by pathname - this is awkward due to
4692 potential access conflicts on the open, but it is unavoidable for these
4693 old servers since the only other choice is to go from 100 nanosecond DCE
4694 time and resort to the original setpathinfo level which takes the ancient
4695 DOS time format with 2 second granularity */
4697 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4698 const FILE_BASIC_INFO *data, __u16 fid)
4700 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4701 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4704 int bytes_returned = 0;
4705 __u16 params, param_offset, offset, byte_count, count;
4707 cFYI(1, ("Set Times (via SetFileInfo)"));
4708 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4713 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4715 /* At this point there is no need to override the current pid
4716 with the pid of the opener, but that could change if we someday
4717 use an existing handle (rather than opening one on the fly) */
4718 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4719 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4722 pSMB->MaxSetupCount = 0;
4726 pSMB->Reserved2 = 0;
4727 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4728 offset = param_offset + params;
4730 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4732 count = sizeof (FILE_BASIC_INFO);
4733 pSMB->MaxParameterCount = cpu_to_le16(2);
4734 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4735 pSMB->SetupCount = 1;
4736 pSMB->Reserved3 = 0;
4737 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4738 byte_count = 3 /* pad */ + params + count;
4739 pSMB->DataCount = cpu_to_le16(count);
4740 pSMB->ParameterCount = cpu_to_le16(params);
4741 pSMB->TotalDataCount = pSMB->DataCount;
4742 pSMB->TotalParameterCount = pSMB->ParameterCount;
4743 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4744 pSMB->DataOffset = cpu_to_le16(offset);
4746 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4747 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4749 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4750 pSMB->Reserved4 = 0;
4751 pSMB->hdr.smb_buf_length += byte_count;
4752 pSMB->ByteCount = cpu_to_le16(byte_count);
4753 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4757 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4760 cifs_small_buf_release(pSMB);
4762 /* Note: On -EAGAIN error only caller can retry on handle based calls
4763 since file handle passed in no longer valid */
4770 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4771 const FILE_BASIC_INFO *data,
4772 const struct nls_table *nls_codepage, int remap)
4774 TRANSACTION2_SPI_REQ *pSMB = NULL;
4775 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4778 int bytes_returned = 0;
4780 __u16 params, param_offset, offset, byte_count, count;
4782 cFYI(1, ("In SetTimes"));
4785 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4790 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4792 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4793 PATH_MAX, nls_codepage, remap);
4794 name_len++; /* trailing null */
4796 } else { /* BB improve the check for buffer overruns BB */
4797 name_len = strnlen(fileName, PATH_MAX);
4798 name_len++; /* trailing null */
4799 strncpy(pSMB->FileName, fileName, name_len);
4802 params = 6 + name_len;
4803 count = sizeof (FILE_BASIC_INFO);
4804 pSMB->MaxParameterCount = cpu_to_le16(2);
4805 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4806 pSMB->MaxSetupCount = 0;
4810 pSMB->Reserved2 = 0;
4811 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4812 InformationLevel) - 4;
4813 offset = param_offset + params;
4814 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4815 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4816 pSMB->DataOffset = cpu_to_le16(offset);
4817 pSMB->SetupCount = 1;
4818 pSMB->Reserved3 = 0;
4819 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4820 byte_count = 3 /* pad */ + params + count;
4822 pSMB->DataCount = cpu_to_le16(count);
4823 pSMB->ParameterCount = cpu_to_le16(params);
4824 pSMB->TotalDataCount = pSMB->DataCount;
4825 pSMB->TotalParameterCount = pSMB->ParameterCount;
4826 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4827 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4829 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4830 pSMB->Reserved4 = 0;
4831 pSMB->hdr.smb_buf_length += byte_count;
4832 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4833 pSMB->ByteCount = cpu_to_le16(byte_count);
4834 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4837 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4840 cifs_buf_release(pSMB);
4848 /* Can not be used to set time stamps yet (due to old DOS time format) */
4849 /* Can be used to set attributes */
4850 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4851 handling it anyway and NT4 was what we thought it would be needed for
4852 Do not delete it until we prove whether needed for Win9x though */
4854 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4855 __u16 dos_attrs, const struct nls_table *nls_codepage)
4857 SETATTR_REQ *pSMB = NULL;
4858 SETATTR_RSP *pSMBr = NULL;
4863 cFYI(1, ("In SetAttrLegacy"));
4866 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4871 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4873 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4874 PATH_MAX, nls_codepage);
4875 name_len++; /* trailing null */
4877 } else { /* BB improve the check for buffer overruns BB */
4878 name_len = strnlen(fileName, PATH_MAX);
4879 name_len++; /* trailing null */
4880 strncpy(pSMB->fileName, fileName, name_len);
4882 pSMB->attr = cpu_to_le16(dos_attrs);
4883 pSMB->BufferFormat = 0x04;
4884 pSMB->hdr.smb_buf_length += name_len + 1;
4885 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4886 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4887 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4889 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4892 cifs_buf_release(pSMB);
4895 goto SetAttrLgcyRetry;
4899 #endif /* temporarily unneeded SetAttr legacy function */
4902 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4903 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4904 dev_t device, const struct nls_table *nls_codepage,
4907 TRANSACTION2_SPI_REQ *pSMB = NULL;
4908 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4911 int bytes_returned = 0;
4912 FILE_UNIX_BASIC_INFO *data_offset;
4913 __u16 params, param_offset, offset, count, byte_count;
4915 cFYI(1, ("In SetUID/GID/Mode"));
4917 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4922 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4924 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4925 PATH_MAX, nls_codepage, remap);
4926 name_len++; /* trailing null */
4928 } else { /* BB improve the check for buffer overruns BB */
4929 name_len = strnlen(fileName, PATH_MAX);
4930 name_len++; /* trailing null */
4931 strncpy(pSMB->FileName, fileName, name_len);
4934 params = 6 + name_len;
4935 count = sizeof (FILE_UNIX_BASIC_INFO);
4936 pSMB->MaxParameterCount = cpu_to_le16(2);
4937 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4938 pSMB->MaxSetupCount = 0;
4942 pSMB->Reserved2 = 0;
4943 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4944 InformationLevel) - 4;
4945 offset = param_offset + params;
4947 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4949 memset(data_offset, 0, count);
4950 pSMB->DataOffset = cpu_to_le16(offset);
4951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4952 pSMB->SetupCount = 1;
4953 pSMB->Reserved3 = 0;
4954 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4955 byte_count = 3 /* pad */ + params + count;
4956 pSMB->ParameterCount = cpu_to_le16(params);
4957 pSMB->DataCount = cpu_to_le16(count);
4958 pSMB->TotalParameterCount = pSMB->ParameterCount;
4959 pSMB->TotalDataCount = pSMB->DataCount;
4960 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4961 pSMB->Reserved4 = 0;
4962 pSMB->hdr.smb_buf_length += byte_count;
4963 /* Samba server ignores set of file size to zero due to bugs in some
4964 older clients, but we should be precise - we use SetFileSize to
4965 set file size and do not want to truncate file size to zero
4966 accidently as happened on one Samba server beta by putting
4967 zero instead of -1 here */
4968 data_offset->EndOfFile = NO_CHANGE_64;
4969 data_offset->NumOfBytes = NO_CHANGE_64;
4970 data_offset->LastStatusChange = NO_CHANGE_64;
4971 data_offset->LastAccessTime = NO_CHANGE_64;
4972 data_offset->LastModificationTime = NO_CHANGE_64;
4973 data_offset->Uid = cpu_to_le64(uid);
4974 data_offset->Gid = cpu_to_le64(gid);
4975 /* better to leave device as zero when it is */
4976 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4977 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4978 data_offset->Permissions = cpu_to_le64(mode);
4981 data_offset->Type = cpu_to_le32(UNIX_FILE);
4982 else if (S_ISDIR(mode))
4983 data_offset->Type = cpu_to_le32(UNIX_DIR);
4984 else if (S_ISLNK(mode))
4985 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4986 else if (S_ISCHR(mode))
4987 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4988 else if (S_ISBLK(mode))
4989 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4990 else if (S_ISFIFO(mode))
4991 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4992 else if (S_ISSOCK(mode))
4993 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4996 pSMB->ByteCount = cpu_to_le16(byte_count);
4997 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4998 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5000 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5004 cifs_buf_release(pSMB);
5010 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5011 const int notify_subdirs, const __u16 netfid,
5012 __u32 filter, struct file *pfile, int multishot,
5013 const struct nls_table *nls_codepage)
5016 struct smb_com_transaction_change_notify_req *pSMB = NULL;
5017 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5018 struct dir_notify_req *dnotify_req;
5021 cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5022 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5027 pSMB->TotalParameterCount = 0 ;
5028 pSMB->TotalDataCount = 0;
5029 pSMB->MaxParameterCount = cpu_to_le32(2);
5030 /* BB find exact data count max from sess structure BB */
5031 pSMB->MaxDataCount = 0; /* same in little endian or be */
5032 /* BB VERIFY verify which is correct for above BB */
5033 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5034 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5036 pSMB->MaxSetupCount = 4;
5038 pSMB->ParameterOffset = 0;
5039 pSMB->DataCount = 0;
5040 pSMB->DataOffset = 0;
5041 pSMB->SetupCount = 4; /* single byte does not need le conversion */
5042 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5043 pSMB->ParameterCount = pSMB->TotalParameterCount;
5045 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5046 pSMB->Reserved2 = 0;
5047 pSMB->CompletionFilter = cpu_to_le32(filter);
5048 pSMB->Fid = netfid; /* file handle always le */
5049 pSMB->ByteCount = 0;
5051 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5052 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
5054 cFYI(1, ("Error in Notify = %d", rc));
5056 /* Add file to outstanding requests */
5057 /* BB change to kmem cache alloc */
5058 dnotify_req = kmalloc(
5059 sizeof(struct dir_notify_req),
5062 dnotify_req->Pid = pSMB->hdr.Pid;
5063 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5064 dnotify_req->Mid = pSMB->hdr.Mid;
5065 dnotify_req->Tid = pSMB->hdr.Tid;
5066 dnotify_req->Uid = pSMB->hdr.Uid;
5067 dnotify_req->netfid = netfid;
5068 dnotify_req->pfile = pfile;
5069 dnotify_req->filter = filter;
5070 dnotify_req->multishot = multishot;
5071 spin_lock(&GlobalMid_Lock);
5072 list_add_tail(&dnotify_req->lhead,
5073 &GlobalDnotifyReqList);
5074 spin_unlock(&GlobalMid_Lock);
5078 cifs_buf_release(pSMB);
5081 #ifdef CONFIG_CIFS_XATTR
5083 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5084 const unsigned char *searchName,
5085 char *EAData, size_t buf_size,
5086 const struct nls_table *nls_codepage, int remap)
5088 /* BB assumes one setup word */
5089 TRANSACTION2_QPI_REQ *pSMB = NULL;
5090 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5094 struct fea *temp_fea;
5096 __u16 params, byte_count;
5098 cFYI(1, ("In Query All EAs path %s", searchName));
5100 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5105 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5107 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5108 PATH_MAX, nls_codepage, remap);
5109 name_len++; /* trailing null */
5111 } else { /* BB improve the check for buffer overruns BB */
5112 name_len = strnlen(searchName, PATH_MAX);
5113 name_len++; /* trailing null */
5114 strncpy(pSMB->FileName, searchName, name_len);
5117 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5118 pSMB->TotalDataCount = 0;
5119 pSMB->MaxParameterCount = cpu_to_le16(2);
5120 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5121 pSMB->MaxSetupCount = 0;
5125 pSMB->Reserved2 = 0;
5126 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5127 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5128 pSMB->DataCount = 0;
5129 pSMB->DataOffset = 0;
5130 pSMB->SetupCount = 1;
5131 pSMB->Reserved3 = 0;
5132 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5133 byte_count = params + 1 /* pad */ ;
5134 pSMB->TotalParameterCount = cpu_to_le16(params);
5135 pSMB->ParameterCount = pSMB->TotalParameterCount;
5136 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5137 pSMB->Reserved4 = 0;
5138 pSMB->hdr.smb_buf_length += byte_count;
5139 pSMB->ByteCount = cpu_to_le16(byte_count);
5141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5144 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5145 } else { /* decode response */
5146 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5148 /* BB also check enough total bytes returned */
5149 /* BB we need to improve the validity checking
5150 of these trans2 responses */
5151 if (rc || (pSMBr->ByteCount < 4))
5152 rc = -EIO; /* bad smb */
5153 /* else if (pFindData){
5154 memcpy((char *) pFindData,
5155 (char *) &pSMBr->hdr.Protocol +
5158 /* check that length of list is not more than bcc */
5159 /* check that each entry does not go beyond length
5161 /* check that each element of each entry does not
5162 go beyond end of list */
5163 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5164 struct fealist *ea_response_data;
5166 /* validate_trans2_offsets() */
5167 /* BB check if start of smb + data_offset > &bcc+ bcc */
5168 ea_response_data = (struct fealist *)
5169 (((char *) &pSMBr->hdr.Protocol) +
5171 name_len = le32_to_cpu(ea_response_data->list_len);
5172 cFYI(1, ("ea length %d", name_len));
5173 if (name_len <= 8) {
5174 /* returned EA size zeroed at top of function */
5175 cFYI(1, ("empty EA list returned from server"));
5177 /* account for ea list len */
5179 temp_fea = ea_response_data->list;
5180 temp_ptr = (char *)temp_fea;
5181 while (name_len > 0) {
5185 rc += temp_fea->name_len;
5186 /* account for prefix user. and trailing null */
5188 if (rc < (int)buf_size) {
5189 memcpy(EAData, "user.", 5);
5191 memcpy(EAData, temp_ptr,
5192 temp_fea->name_len);
5193 EAData += temp_fea->name_len;
5194 /* null terminate name */
5196 EAData = EAData + 1;
5197 } else if (buf_size == 0) {
5198 /* skip copy - calc size only */
5200 /* stop before overrun buffer */
5204 name_len -= temp_fea->name_len;
5205 temp_ptr += temp_fea->name_len;
5206 /* account for trailing null */
5210 le16_to_cpu(temp_fea->value_len);
5211 name_len -= value_len;
5212 temp_ptr += value_len;
5213 /* BB check that temp_ptr is still
5216 /* no trailing null to account for
5218 /* go on to next EA */
5219 temp_fea = (struct fea *)temp_ptr;
5225 cifs_buf_release(pSMB);
5232 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5233 const unsigned char *searchName, const unsigned char *ea_name,
5234 unsigned char *ea_value, size_t buf_size,
5235 const struct nls_table *nls_codepage, int remap)
5237 TRANSACTION2_QPI_REQ *pSMB = NULL;
5238 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5242 struct fea *temp_fea;
5244 __u16 params, byte_count;
5246 cFYI(1, ("In Query EA path %s", searchName));
5248 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5253 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5255 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5256 PATH_MAX, nls_codepage, remap);
5257 name_len++; /* trailing null */
5259 } else { /* BB improve the check for buffer overruns BB */
5260 name_len = strnlen(searchName, PATH_MAX);
5261 name_len++; /* trailing null */
5262 strncpy(pSMB->FileName, searchName, name_len);
5265 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5266 pSMB->TotalDataCount = 0;
5267 pSMB->MaxParameterCount = cpu_to_le16(2);
5268 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
5269 pSMB->MaxSetupCount = 0;
5273 pSMB->Reserved2 = 0;
5274 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5275 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5276 pSMB->DataCount = 0;
5277 pSMB->DataOffset = 0;
5278 pSMB->SetupCount = 1;
5279 pSMB->Reserved3 = 0;
5280 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5281 byte_count = params + 1 /* pad */ ;
5282 pSMB->TotalParameterCount = cpu_to_le16(params);
5283 pSMB->ParameterCount = pSMB->TotalParameterCount;
5284 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5285 pSMB->Reserved4 = 0;
5286 pSMB->hdr.smb_buf_length += byte_count;
5287 pSMB->ByteCount = cpu_to_le16(byte_count);
5289 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5290 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5292 cFYI(1, ("Send error in Query EA = %d", rc));
5293 } else { /* decode response */
5294 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5296 /* BB also check enough total bytes returned */
5297 /* BB we need to improve the validity checking
5298 of these trans2 responses */
5299 if (rc || (pSMBr->ByteCount < 4))
5300 rc = -EIO; /* bad smb */
5301 /* else if (pFindData){
5302 memcpy((char *) pFindData,
5303 (char *) &pSMBr->hdr.Protocol +
5306 /* check that length of list is not more than bcc */
5307 /* check that each entry does not go beyond length
5309 /* check that each element of each entry does not
5310 go beyond end of list */
5311 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5312 struct fealist *ea_response_data;
5314 /* validate_trans2_offsets() */
5315 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5316 ea_response_data = (struct fealist *)
5317 (((char *) &pSMBr->hdr.Protocol) +
5319 name_len = le32_to_cpu(ea_response_data->list_len);
5320 cFYI(1, ("ea length %d", name_len));
5321 if (name_len <= 8) {
5322 /* returned EA size zeroed at top of function */
5323 cFYI(1, ("empty EA list returned from server"));
5325 /* account for ea list len */
5327 temp_fea = ea_response_data->list;
5328 temp_ptr = (char *)temp_fea;
5329 /* loop through checking if we have a matching
5330 name and then return the associated value */
5331 while (name_len > 0) {
5336 le16_to_cpu(temp_fea->value_len);
5337 /* BB validate that value_len falls within SMB,
5338 even though maximum for name_len is 255 */
5339 if (memcmp(temp_fea->name, ea_name,
5340 temp_fea->name_len) == 0) {
5343 /* account for prefix user. and trailing null */
5344 if (rc <= (int)buf_size) {
5346 temp_fea->name+temp_fea->name_len+1,
5348 /* ea values, unlike ea
5351 } else if (buf_size == 0) {
5352 /* skip copy - calc size only */
5354 /* stop before overrun buffer */
5359 name_len -= temp_fea->name_len;
5360 temp_ptr += temp_fea->name_len;
5361 /* account for trailing null */
5364 name_len -= value_len;
5365 temp_ptr += value_len;
5366 /* No trailing null to account for in
5367 value_len. Go on to next EA */
5368 temp_fea = (struct fea *)temp_ptr;
5374 cifs_buf_release(pSMB);
5382 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5383 const char *ea_name, const void *ea_value,
5384 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5387 struct smb_com_transaction2_spi_req *pSMB = NULL;
5388 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5389 struct fealist *parm_data;
5392 int bytes_returned = 0;
5393 __u16 params, param_offset, byte_count, offset, count;
5395 cFYI(1, ("In SetEA"));
5397 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5402 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5404 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5405 PATH_MAX, nls_codepage, remap);
5406 name_len++; /* trailing null */
5408 } else { /* BB improve the check for buffer overruns BB */
5409 name_len = strnlen(fileName, PATH_MAX);
5410 name_len++; /* trailing null */
5411 strncpy(pSMB->FileName, fileName, name_len);
5414 params = 6 + name_len;
5416 /* done calculating parms using name_len of file name,
5417 now use name_len to calculate length of ea name
5418 we are going to create in the inode xattrs */
5419 if (ea_name == NULL)
5422 name_len = strnlen(ea_name, 255);
5424 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
5425 pSMB->MaxParameterCount = cpu_to_le16(2);
5426 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
5427 pSMB->MaxSetupCount = 0;
5431 pSMB->Reserved2 = 0;
5432 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5433 InformationLevel) - 4;
5434 offset = param_offset + params;
5435 pSMB->InformationLevel =
5436 cpu_to_le16(SMB_SET_FILE_EA);
5439 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5441 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5442 pSMB->DataOffset = cpu_to_le16(offset);
5443 pSMB->SetupCount = 1;
5444 pSMB->Reserved3 = 0;
5445 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5446 byte_count = 3 /* pad */ + params + count;
5447 pSMB->DataCount = cpu_to_le16(count);
5448 parm_data->list_len = cpu_to_le32(count);
5449 parm_data->list[0].EA_flags = 0;
5450 /* we checked above that name len is less than 255 */
5451 parm_data->list[0].name_len = (__u8)name_len;
5452 /* EA names are always ASCII */
5454 strncpy(parm_data->list[0].name, ea_name, name_len);
5455 parm_data->list[0].name[name_len] = 0;
5456 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5457 /* caller ensures that ea_value_len is less than 64K but
5458 we need to ensure that it fits within the smb */
5460 /*BB add length check to see if it would fit in
5461 negotiated SMB buffer size BB */
5462 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5464 memcpy(parm_data->list[0].name+name_len+1,
5465 ea_value, ea_value_len);
5467 pSMB->TotalDataCount = pSMB->DataCount;
5468 pSMB->ParameterCount = cpu_to_le16(params);
5469 pSMB->TotalParameterCount = pSMB->ParameterCount;
5470 pSMB->Reserved4 = 0;
5471 pSMB->hdr.smb_buf_length += byte_count;
5472 pSMB->ByteCount = cpu_to_le16(byte_count);
5473 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5474 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5476 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5479 cifs_buf_release(pSMB);