4 * Copyright (C) International Business Machines Corp., 2002,2005
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 different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
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 {CIFS_PROT, "\2NT LM 0.12"},
48 {CIFS_PROT, "\2POSIX 2"},
56 {CIFS_PROT, "\2NT LM 0.12"},
62 /* Mark as invalid, all open files on tree connections since they
63 were closed when session to server was lost */
64 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
66 struct cifsFileInfo *open_file = NULL;
67 struct list_head * tmp;
68 struct list_head * tmp1;
70 /* list all files open on tree connection and mark them invalid */
71 write_lock(&GlobalSMBSeslock);
72 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
73 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
75 open_file->invalidHandle = TRUE;
78 write_unlock(&GlobalSMBSeslock);
79 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
83 /* If the return code is zero, this function must fill in request_buf pointer */
85 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
86 void **request_buf /* returned */)
90 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
91 check for tcp and smb session status done differently
92 for those three - in the calling routine */
94 if(tcon->tidStatus == CifsExiting) {
95 /* only tree disconnect, open, and write,
96 (and ulogoff which does not have tcon)
97 are allowed as we start force umount */
98 if((smb_command != SMB_COM_WRITE_ANDX) &&
99 (smb_command != SMB_COM_OPEN_ANDX) &&
100 (smb_command != SMB_COM_TREE_DISCONNECT)) {
101 cFYI(1,("can not send cmd %d while umounting",
106 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
107 (tcon->ses->server)){
108 struct nls_table *nls_codepage;
109 /* Give Demultiplex thread up to 10 seconds to
110 reconnect, should be greater than cifs socket
111 timeout which is 7 seconds */
112 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
113 wait_event_interruptible_timeout(tcon->ses->server->response_q,
114 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
115 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
116 /* on "soft" mounts we wait once */
117 if((tcon->retry == FALSE) ||
118 (tcon->ses->status == CifsExiting)) {
119 cFYI(1,("gave up waiting on reconnect in smb_init"));
121 } /* else "hard" mount - keep retrying
122 until process is killed or server
123 comes back on-line */
124 } else /* TCP session is reestablished now */
129 nls_codepage = load_nls_default();
130 /* need to prevent multiple threads trying to
131 simultaneously reconnect the same SMB session */
132 down(&tcon->ses->sesSem);
133 if(tcon->ses->status == CifsNeedReconnect)
134 rc = cifs_setup_session(0, tcon->ses,
136 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
137 mark_open_files_invalid(tcon);
138 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
140 up(&tcon->ses->sesSem);
141 /* BB FIXME add code to check if wsize needs
142 update due to negotiated smb buffer size
145 atomic_inc(&tconInfoReconnectCount);
147 cFYI(1, ("reconnect tcon rc = %d", rc));
148 /* Removed call to reopen open files here -
149 it is safer (and faster) to reopen files
150 one at a time as needed in read and write */
152 /* Check if handle based operation so we
153 know whether we can continue or not without
154 returning to caller to reset file handle */
155 switch(smb_command) {
156 case SMB_COM_READ_ANDX:
157 case SMB_COM_WRITE_ANDX:
159 case SMB_COM_FIND_CLOSE2:
160 case SMB_COM_LOCKING_ANDX: {
161 unload_nls(nls_codepage);
166 up(&tcon->ses->sesSem);
168 unload_nls(nls_codepage);
177 *request_buf = cifs_small_buf_get();
178 if (*request_buf == NULL) {
179 /* BB should we add a retry in here if not a writepage? */
183 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
186 cifs_stats_inc(&tcon->num_smbs_sent);
191 /* If the return code is zero, this function must fill in request_buf pointer */
193 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
194 void **request_buf /* returned */ ,
195 void **response_buf /* returned */ )
199 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
200 check for tcp and smb session status done differently
201 for those three - in the calling routine */
203 if(tcon->tidStatus == CifsExiting) {
204 /* only tree disconnect, open, and write,
205 (and ulogoff which does not have tcon)
206 are allowed as we start force umount */
207 if((smb_command != SMB_COM_WRITE_ANDX) &&
208 (smb_command != SMB_COM_OPEN_ANDX) &&
209 (smb_command != SMB_COM_TREE_DISCONNECT)) {
210 cFYI(1,("can not send cmd %d while umounting",
216 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
217 (tcon->ses->server)){
218 struct nls_table *nls_codepage;
219 /* Give Demultiplex thread up to 10 seconds to
220 reconnect, should be greater than cifs socket
221 timeout which is 7 seconds */
222 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
223 wait_event_interruptible_timeout(tcon->ses->server->response_q,
224 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
225 if(tcon->ses->server->tcpStatus ==
227 /* on "soft" mounts we wait once */
228 if((tcon->retry == FALSE) ||
229 (tcon->ses->status == CifsExiting)) {
230 cFYI(1,("gave up waiting on reconnect in smb_init"));
232 } /* else "hard" mount - keep retrying
233 until process is killed or server
235 } else /* TCP session is reestablished now */
240 nls_codepage = load_nls_default();
241 /* need to prevent multiple threads trying to
242 simultaneously reconnect the same SMB session */
243 down(&tcon->ses->sesSem);
244 if(tcon->ses->status == CifsNeedReconnect)
245 rc = cifs_setup_session(0, tcon->ses,
247 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
248 mark_open_files_invalid(tcon);
249 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
251 up(&tcon->ses->sesSem);
252 /* BB FIXME add code to check if wsize needs
253 update due to negotiated smb buffer size
256 atomic_inc(&tconInfoReconnectCount);
258 cFYI(1, ("reconnect tcon rc = %d", rc));
259 /* Removed call to reopen open files here -
260 it is safer (and faster) to reopen files
261 one at a time as needed in read and write */
263 /* Check if handle based operation so we
264 know whether we can continue or not without
265 returning to caller to reset file handle */
266 switch(smb_command) {
267 case SMB_COM_READ_ANDX:
268 case SMB_COM_WRITE_ANDX:
270 case SMB_COM_FIND_CLOSE2:
271 case SMB_COM_LOCKING_ANDX: {
272 unload_nls(nls_codepage);
277 up(&tcon->ses->sesSem);
279 unload_nls(nls_codepage);
288 *request_buf = cifs_buf_get();
289 if (*request_buf == NULL) {
290 /* BB should we add a retry in here if not a writepage? */
293 /* Although the original thought was we needed the response buf for */
294 /* potential retries of smb operations it turns out we can determine */
295 /* from the mid flags when the request buffer can be resent without */
296 /* having to use a second distinct buffer for the response */
297 *response_buf = *request_buf;
299 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
303 cifs_stats_inc(&tcon->num_smbs_sent);
308 static int validate_t2(struct smb_t2_rsp * pSMB)
314 /* check for plausible wct, bcc and t2 data and parm sizes */
315 /* check for parm and data offset going beyond end of smb */
316 if(pSMB->hdr.WordCount >= 10) {
317 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
318 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
319 /* check that bcc is at least as big as parms + data */
320 /* check that bcc is less than negotiated smb buffer */
321 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
322 if(total_size < 512) {
323 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
324 /* BCC le converted in SendReceive */
325 pBCC = (pSMB->hdr.WordCount * 2) +
326 sizeof(struct smb_hdr) +
328 if((total_size <= (*(u16 *)pBCC)) &&
330 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
337 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
338 sizeof(struct smb_t2_rsp) + 16);
342 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
345 NEGOTIATE_RSP *pSMBr;
348 struct TCP_Server_Info * server;
352 server = ses->server;
357 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
358 (void **) &pSMB, (void **) &pSMBr);
361 pSMB->hdr.Mid = GetNextMid(server);
362 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
363 if (extended_security)
364 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
366 count = strlen(protocols[0].name) + 1;
367 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
368 /* null guaranteed to be at end of source and target buffers anyway */
370 pSMB->hdr.smb_buf_length += count;
371 pSMB->ByteCount = cpu_to_le16(count);
373 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
374 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
376 server->secMode = pSMBr->SecurityMode;
377 if((server->secMode & SECMODE_USER) == 0)
378 cFYI(1,("share mode security"));
379 server->secType = NTLM; /* BB override default for
380 NTLMv2 or kerberos v5 */
381 /* one byte - no need to convert this or EncryptionKeyLen
382 from little endian */
383 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
384 /* probably no need to store and check maxvcs */
386 min(le32_to_cpu(pSMBr->MaxBufferSize),
387 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
388 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
389 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
390 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
391 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
392 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
393 /* BB with UTC do we ever need to be using srvr timezone? */
394 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
395 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
396 CIFS_CRYPTO_KEY_SIZE);
397 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
398 && (pSMBr->EncryptionKeyLength == 0)) {
399 /* decode security blob */
403 /* BB might be helpful to save off the domain of server here */
405 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
406 (server->capabilities & CAP_EXTENDED_SECURITY)) {
407 count = pSMBr->ByteCount;
410 else if (count == 16) {
411 server->secType = RawNTLMSSP;
412 if (server->socketUseCount.counter > 1) {
414 (server->server_GUID,
415 pSMBr->u.extended_response.
417 cFYI(1, ("server UID changed"));
425 memcpy(server->server_GUID,
426 pSMBr->u.extended_response.
429 rc = decode_negTokenInit(pSMBr->u.
435 /* BB Need to fill struct for sessetup here */
442 server->capabilities &= ~CAP_EXTENDED_SECURITY;
443 if(sign_CIFS_PDUs == FALSE) {
444 if(server->secMode & SECMODE_SIGN_REQUIRED)
446 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
447 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
448 } else if(sign_CIFS_PDUs == 1) {
449 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
450 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
455 cifs_buf_release(pSMB);
460 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
462 struct smb_hdr *smb_buffer;
463 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
467 cFYI(1, ("In tree disconnect"));
469 * If last user of the connection and
470 * connection alive - disconnect it
471 * If this is the last connection on the server session disconnect it
472 * (and inside session disconnect we should check if tcp socket needs
473 * to be freed and kernel thread woken up).
476 down(&tcon->tconSem);
480 atomic_dec(&tcon->useCount);
481 if (atomic_read(&tcon->useCount) > 0) {
486 /* No need to return error on this operation if tid invalidated and
487 closed on server already e.g. due to tcp session crashing */
488 if(tcon->tidStatus == CifsNeedReconnect) {
493 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
497 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
498 (void **)&smb_buffer);
503 smb_buffer_response = smb_buffer; /* BB removeme BB */
505 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
508 cFYI(1, ("Tree disconnect failed %d", rc));
511 cifs_small_buf_release(smb_buffer);
514 /* No need to return error on this operation if tid invalidated and
515 closed on server already e.g. due to tcp session crashing */
523 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
525 struct smb_hdr *smb_buffer_response;
526 LOGOFF_ANDX_REQ *pSMB;
530 cFYI(1, ("In SMBLogoff for session disconnect"));
536 atomic_dec(&ses->inUse);
537 if (atomic_read(&ses->inUse) > 0) {
541 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
547 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
550 pSMB->hdr.Mid = GetNextMid(ses->server);
552 if(ses->server->secMode &
553 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
554 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
557 pSMB->hdr.Uid = ses->Suid;
559 pSMB->AndXCommand = 0xFF;
560 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
561 smb_buffer_response, &length, 0);
563 atomic_dec(&ses->server->socketUseCount);
564 if (atomic_read(&ses->server->socketUseCount) == 0) {
565 spin_lock(&GlobalMid_Lock);
566 ses->server->tcpStatus = CifsExiting;
567 spin_unlock(&GlobalMid_Lock);
572 cifs_small_buf_release(pSMB);
574 /* if session dead then we do not need to do ulogoff,
575 since server closed smb session, no sense reporting
583 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
584 const struct nls_table *nls_codepage, int remap)
586 DELETE_FILE_REQ *pSMB = NULL;
587 DELETE_FILE_RSP *pSMBr = NULL;
593 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
598 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
600 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
601 PATH_MAX, nls_codepage, remap);
602 name_len++; /* trailing null */
604 } else { /* BB improve check for buffer overruns BB */
605 name_len = strnlen(fileName, PATH_MAX);
606 name_len++; /* trailing null */
607 strncpy(pSMB->fileName, fileName, name_len);
609 pSMB->SearchAttributes =
610 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
611 pSMB->BufferFormat = 0x04;
612 pSMB->hdr.smb_buf_length += name_len + 1;
613 pSMB->ByteCount = cpu_to_le16(name_len + 1);
614 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
615 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
616 cifs_stats_inc(&tcon->num_deletes);
618 cFYI(1, ("Error in RMFile = %d", rc));
621 cifs_buf_release(pSMB);
629 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
630 const struct nls_table *nls_codepage, int remap)
632 DELETE_DIRECTORY_REQ *pSMB = NULL;
633 DELETE_DIRECTORY_RSP *pSMBr = NULL;
638 cFYI(1, ("In CIFSSMBRmDir"));
640 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
645 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
646 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
647 PATH_MAX, nls_codepage, remap);
648 name_len++; /* trailing null */
650 } else { /* BB improve check for buffer overruns BB */
651 name_len = strnlen(dirName, PATH_MAX);
652 name_len++; /* trailing null */
653 strncpy(pSMB->DirName, dirName, name_len);
656 pSMB->BufferFormat = 0x04;
657 pSMB->hdr.smb_buf_length += name_len + 1;
658 pSMB->ByteCount = cpu_to_le16(name_len + 1);
659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
661 cifs_stats_inc(&tcon->num_rmdirs);
663 cFYI(1, ("Error in RMDir = %d", rc));
666 cifs_buf_release(pSMB);
673 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
674 const char *name, const struct nls_table *nls_codepage, int remap)
677 CREATE_DIRECTORY_REQ *pSMB = NULL;
678 CREATE_DIRECTORY_RSP *pSMBr = NULL;
682 cFYI(1, ("In CIFSSMBMkDir"));
684 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
689 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
690 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
691 PATH_MAX, nls_codepage, remap);
692 name_len++; /* trailing null */
694 } else { /* BB improve check for buffer overruns BB */
695 name_len = strnlen(name, PATH_MAX);
696 name_len++; /* trailing null */
697 strncpy(pSMB->DirName, name, name_len);
700 pSMB->BufferFormat = 0x04;
701 pSMB->hdr.smb_buf_length += name_len + 1;
702 pSMB->ByteCount = cpu_to_le16(name_len + 1);
703 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
704 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
705 cifs_stats_inc(&tcon->num_mkdirs);
707 cFYI(1, ("Error in Mkdir = %d", rc));
710 cifs_buf_release(pSMB);
716 static __u16 convert_disposition(int disposition)
720 switch (disposition) {
722 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
725 ofun = SMBOPEN_OAPPEND;
728 ofun = SMBOPEN_OCREATE;
731 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
734 ofun = SMBOPEN_OTRUNC;
736 case FILE_OVERWRITE_IF:
737 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
740 cFYI(1,("unknown disposition %d",disposition));
741 ofun = SMBOPEN_OAPPEND; /* regular open */
747 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
748 const char *fileName, const int openDisposition,
749 const int access_flags, const int create_options, __u16 * netfid,
750 int *pOplock, FILE_ALL_INFO * pfile_info,
751 const struct nls_table *nls_codepage, int remap)
754 OPENX_REQ *pSMB = NULL;
755 OPENX_RSP *pSMBr = NULL;
761 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
766 pSMB->AndXCommand = 0xFF; /* none */
768 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
769 count = 1; /* account for one byte pad to word boundary */
771 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
772 fileName, PATH_MAX, nls_codepage, remap);
773 name_len++; /* trailing null */
775 } else { /* BB improve check for buffer overruns BB */
776 count = 0; /* no pad */
777 name_len = strnlen(fileName, PATH_MAX);
778 name_len++; /* trailing null */
779 strncpy(pSMB->fileName, fileName, name_len);
781 if (*pOplock & REQ_OPLOCK)
782 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
783 else if (*pOplock & REQ_BATCHOPLOCK) {
784 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
786 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
787 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
793 pSMB->Mode = cpu_to_le16(2);
794 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
795 /* set file as system file if special file such
796 as fifo and server expecting SFU style and
797 no Unix extensions */
799 if(create_options & CREATE_OPTION_SPECIAL)
800 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
802 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
804 /* if ((omode & S_IWUGO) == 0)
805 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
806 /* Above line causes problems due to vfs splitting create into two
807 pieces - need to set mode after file created not while it is
811 /* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
812 /* BB FIXME END BB */
814 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
815 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
817 pSMB->hdr.smb_buf_length += count;
819 pSMB->ByteCount = cpu_to_le16(count);
820 /* long_op set to 1 to allow for oplock break timeouts */
821 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
822 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
823 cifs_stats_inc(&tcon->num_opens);
825 cFYI(1, ("Error in Open = %d", rc));
827 /* BB verify if wct == 15 */
829 /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
831 *netfid = pSMBr->Fid; /* cifs fid stays in le */
832 /* Let caller know file was created so we can set the mode. */
833 /* Do we care about the CreateAction in any other cases? */
835 /* if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
836 *pOplock |= CIFS_CREATE_ACTION; */
840 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
841 pfile_info->LastAccessTime = 0; /* BB fixme */
842 pfile_info->LastWriteTime = 0; /* BB fixme */
843 pfile_info->ChangeTime = 0; /* BB fixme */
844 pfile_info->Attributes =
845 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
846 /* the file_info buf is endian converted by caller */
847 pfile_info->AllocationSize =
848 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
849 pfile_info->EndOfFile = pfile_info->AllocationSize;
850 pfile_info->NumberOfLinks = cpu_to_le32(1);
854 cifs_buf_release(pSMB);
861 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
862 const char *fileName, const int openDisposition,
863 const int access_flags, const int create_options, __u16 * netfid,
864 int *pOplock, FILE_ALL_INFO * pfile_info,
865 const struct nls_table *nls_codepage, int remap)
868 OPEN_REQ *pSMB = NULL;
869 OPEN_RSP *pSMBr = NULL;
875 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
880 pSMB->AndXCommand = 0xFF; /* none */
882 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
883 count = 1; /* account for one byte pad to word boundary */
885 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
886 fileName, PATH_MAX, nls_codepage, remap);
887 name_len++; /* trailing null */
889 pSMB->NameLength = cpu_to_le16(name_len);
890 } else { /* BB improve check for buffer overruns BB */
891 count = 0; /* no pad */
892 name_len = strnlen(fileName, PATH_MAX);
893 name_len++; /* trailing null */
894 pSMB->NameLength = cpu_to_le16(name_len);
895 strncpy(pSMB->fileName, fileName, name_len);
897 if (*pOplock & REQ_OPLOCK)
898 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
899 else if (*pOplock & REQ_BATCHOPLOCK) {
900 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
902 pSMB->DesiredAccess = cpu_to_le32(access_flags);
903 pSMB->AllocationSize = 0;
904 /* set file as system file if special file such
905 as fifo and server expecting SFU style and
906 no Unix extensions */
907 if(create_options & CREATE_OPTION_SPECIAL)
908 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
910 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
911 /* XP does not handle ATTR_POSIX_SEMANTICS */
912 /* but it helps speed up case sensitive checks for other
913 servers such as Samba */
914 if (tcon->ses->capabilities & CAP_UNIX)
915 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
917 /* if ((omode & S_IWUGO) == 0)
918 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
919 /* Above line causes problems due to vfs splitting create into two
920 pieces - need to set mode after file created not while it is
922 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
923 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
924 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
925 /* BB Expirement with various impersonation levels and verify */
926 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
927 pSMB->SecurityFlags =
928 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
931 pSMB->hdr.smb_buf_length += count;
933 pSMB->ByteCount = cpu_to_le16(count);
934 /* long_op set to 1 to allow for oplock break timeouts */
935 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
936 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
937 cifs_stats_inc(&tcon->num_opens);
939 cFYI(1, ("Error in Open = %d", rc));
941 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
942 *netfid = pSMBr->Fid; /* cifs fid stays in le */
943 /* Let caller know file was created so we can set the mode. */
944 /* Do we care about the CreateAction in any other cases? */
945 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
946 *pOplock |= CIFS_CREATE_ACTION;
948 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
949 36 /* CreationTime to Attributes */);
950 /* the file_info buf is endian converted by caller */
951 pfile_info->AllocationSize = pSMBr->AllocationSize;
952 pfile_info->EndOfFile = pSMBr->EndOfFile;
953 pfile_info->NumberOfLinks = cpu_to_le32(1);
957 cifs_buf_release(pSMB);
964 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
965 const int netfid, const unsigned int count,
966 const __u64 lseek, unsigned int *nbytes, char **buf,
970 READ_REQ *pSMB = NULL;
971 READ_RSP *pSMBr = NULL;
972 char *pReadData = NULL;
974 int resp_buf_type = 0;
977 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
978 if(tcon->ses->capabilities & CAP_LARGE_FILES)
981 wct = 10; /* old style read */
984 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
988 /* tcon and ses pointer are checked in smb_init */
989 if (tcon->ses->server == NULL)
990 return -ECONNABORTED;
992 pSMB->AndXCommand = 0xFF; /* none */
994 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
996 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
997 else if((lseek >> 32) > 0) /* can not handle this big offset for old */
1000 pSMB->Remaining = 0;
1001 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1002 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1004 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1006 /* old style read */
1007 struct smb_com_readx_req * pSMBW =
1008 (struct smb_com_readx_req *)pSMB;
1009 pSMBW->ByteCount = 0;
1012 iov[0].iov_base = (char *)pSMB;
1013 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1014 rc = SendReceive2(xid, tcon->ses, iov,
1017 cifs_stats_inc(&tcon->num_reads);
1018 pSMBr = (READ_RSP *)iov[0].iov_base;
1020 cERROR(1, ("Send error in read = %d", rc));
1022 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1023 data_length = data_length << 16;
1024 data_length += le16_to_cpu(pSMBr->DataLength);
1025 *nbytes = data_length;
1027 /*check that DataLength would not go beyond end of SMB */
1028 if ((data_length > CIFSMaxBufSize)
1029 || (data_length > count)) {
1030 cFYI(1,("bad length %d for count %d",data_length,count));
1034 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1035 le16_to_cpu(pSMBr->DataOffset);
1036 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1037 cERROR(1,("Faulting on read rc = %d",rc));
1039 }*/ /* can not use copy_to_user when using page cache*/
1041 memcpy(*buf,pReadData,data_length);
1045 cifs_small_buf_release(pSMB);
1047 if(resp_buf_type == CIFS_SMALL_BUFFER)
1048 cifs_small_buf_release(iov[0].iov_base);
1049 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1050 cifs_buf_release(iov[0].iov_base);
1051 } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1052 *buf = iov[0].iov_base;
1053 if(resp_buf_type == CIFS_SMALL_BUFFER)
1054 *pbuf_type = CIFS_SMALL_BUFFER;
1055 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1056 *pbuf_type = CIFS_LARGE_BUFFER;
1059 /* Note: On -EAGAIN error only caller can retry on handle based calls
1060 since file handle passed in no longer valid */
1066 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1067 const int netfid, const unsigned int count,
1068 const __u64 offset, unsigned int *nbytes, const char *buf,
1069 const char __user * ubuf, const int long_op)
1072 WRITE_REQ *pSMB = NULL;
1073 WRITE_RSP *pSMBr = NULL;
1074 int bytes_returned, wct;
1078 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1079 if(tcon->ses == NULL)
1080 return -ECONNABORTED;
1082 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1087 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1091 /* tcon and ses pointer are checked in smb_init */
1092 if (tcon->ses->server == NULL)
1093 return -ECONNABORTED;
1095 pSMB->AndXCommand = 0xFF; /* none */
1097 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1099 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1100 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1103 pSMB->Reserved = 0xFFFFFFFF;
1104 pSMB->WriteMode = 0;
1105 pSMB->Remaining = 0;
1107 /* Can increase buffer size if buffer is big enough in some cases - ie we
1108 can send more if LARGE_WRITE_X capability returned by the server and if
1109 our buffer is big enough or if we convert to iovecs on socket writes
1110 and eliminate the copy to the CIFS buffer */
1111 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1112 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1114 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1118 if (bytes_sent > count)
1121 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1123 memcpy(pSMB->Data,buf,bytes_sent);
1125 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1126 cifs_buf_release(pSMB);
1129 } else if (count != 0) {
1131 cifs_buf_release(pSMB);
1133 } /* else setting file size with write of zero bytes */
1135 byte_count = bytes_sent + 1; /* pad */
1136 else /* wct == 12 */ {
1137 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1139 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1140 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1141 pSMB->hdr.smb_buf_length += byte_count;
1144 pSMB->ByteCount = cpu_to_le16(byte_count);
1145 else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
1146 struct smb_com_writex_req * pSMBW =
1147 (struct smb_com_writex_req *)pSMB;
1148 pSMBW->ByteCount = cpu_to_le16(byte_count);
1151 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1152 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1153 cifs_stats_inc(&tcon->num_writes);
1155 cFYI(1, ("Send error in write = %d", rc));
1158 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1159 *nbytes = (*nbytes) << 16;
1160 *nbytes += le16_to_cpu(pSMBr->Count);
1163 cifs_buf_release(pSMB);
1165 /* Note: On -EAGAIN error only caller can retry on handle based calls
1166 since file handle passed in no longer valid */
1172 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1173 const int netfid, const unsigned int count,
1174 const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1175 int n_vec, const int long_op)
1178 WRITE_REQ *pSMB = NULL;
1181 int resp_buf_type = 0;
1183 cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
1185 if(tcon->ses->capabilities & CAP_LARGE_FILES)
1189 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1192 /* tcon and ses pointer are checked in smb_init */
1193 if (tcon->ses->server == NULL)
1194 return -ECONNABORTED;
1196 pSMB->AndXCommand = 0xFF; /* none */
1198 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1200 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1201 else if((offset >> 32) > 0) /* can not handle this big offset for old */
1203 pSMB->Reserved = 0xFFFFFFFF;
1204 pSMB->WriteMode = 0;
1205 pSMB->Remaining = 0;
1208 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1210 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1211 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1212 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1214 pSMB->hdr.smb_buf_length += count+1;
1215 else /* wct == 12 */
1216 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1218 pSMB->ByteCount = cpu_to_le16(count + 1);
1219 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1220 struct smb_com_writex_req * pSMBW =
1221 (struct smb_com_writex_req *)pSMB;
1222 pSMBW->ByteCount = cpu_to_le16(count + 5);
1224 iov[0].iov_base = pSMB;
1226 iov[0].iov_len = smb_hdr_len + 4;
1227 else /* wct == 12 pad bigger by four bytes */
1228 iov[0].iov_len = smb_hdr_len + 8;
1231 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1233 cifs_stats_inc(&tcon->num_writes);
1235 cFYI(1, ("Send error Write2 = %d", rc));
1237 } else if(resp_buf_type == 0) {
1238 /* presumably this can not happen, but best to be safe */
1242 WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
1243 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1244 *nbytes = (*nbytes) << 16;
1245 *nbytes += le16_to_cpu(pSMBr->Count);
1248 cifs_small_buf_release(pSMB);
1249 if(resp_buf_type == CIFS_SMALL_BUFFER)
1250 cifs_small_buf_release(iov[0].iov_base);
1251 else if(resp_buf_type == CIFS_LARGE_BUFFER)
1252 cifs_buf_release(iov[0].iov_base);
1254 /* Note: On -EAGAIN error only caller can retry on handle based calls
1255 since file handle passed in no longer valid */
1262 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1263 const __u16 smb_file_id, const __u64 len,
1264 const __u64 offset, const __u32 numUnlock,
1265 const __u32 numLock, const __u8 lockType, const int waitFlag)
1268 LOCK_REQ *pSMB = NULL;
1269 LOCK_RSP *pSMBr = NULL;
1274 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1275 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1280 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1282 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1283 timeout = -1; /* no response expected */
1285 } else if (waitFlag == TRUE) {
1286 timeout = 3; /* blocking operation, no timeout */
1287 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1292 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1293 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1294 pSMB->LockType = lockType;
1295 pSMB->AndXCommand = 0xFF; /* none */
1296 pSMB->Fid = smb_file_id; /* netfid stays le */
1298 if((numLock != 0) || (numUnlock != 0)) {
1299 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1300 /* BB where to store pid high? */
1301 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1302 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1303 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1304 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1305 count = sizeof(LOCKING_ANDX_RANGE);
1310 pSMB->hdr.smb_buf_length += count;
1311 pSMB->ByteCount = cpu_to_le16(count);
1313 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1314 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1315 cifs_stats_inc(&tcon->num_locks);
1317 cFYI(1, ("Send error in Lock = %d", rc));
1319 cifs_small_buf_release(pSMB);
1321 /* Note: On -EAGAIN error only caller can retry on handle based calls
1322 since file handle passed in no longer valid */
1327 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1330 CLOSE_REQ *pSMB = NULL;
1331 CLOSE_RSP *pSMBr = NULL;
1333 cFYI(1, ("In CIFSSMBClose"));
1335 /* do not retry on dead session on close */
1336 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1342 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1344 pSMB->FileID = (__u16) smb_file_id;
1345 pSMB->LastWriteTime = 0;
1346 pSMB->ByteCount = 0;
1347 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1348 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1349 cifs_stats_inc(&tcon->num_closes);
1352 /* EINTR is expected when user ctl-c to kill app */
1353 cERROR(1, ("Send error in Close = %d", rc));
1357 cifs_small_buf_release(pSMB);
1359 /* Since session is dead, file will be closed on server already */
1367 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1368 const char *fromName, const char *toName,
1369 const struct nls_table *nls_codepage, int remap)
1372 RENAME_REQ *pSMB = NULL;
1373 RENAME_RSP *pSMBr = NULL;
1375 int name_len, name_len2;
1378 cFYI(1, ("In CIFSSMBRename"));
1380 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1385 pSMB->BufferFormat = 0x04;
1386 pSMB->SearchAttributes =
1387 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1390 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1392 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1393 PATH_MAX, nls_codepage, remap);
1394 name_len++; /* trailing null */
1396 pSMB->OldFileName[name_len] = 0x04; /* pad */
1397 /* protocol requires ASCII signature byte on Unicode string */
1398 pSMB->OldFileName[name_len + 1] = 0x00;
1400 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1401 toName, PATH_MAX, nls_codepage, remap);
1402 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1403 name_len2 *= 2; /* convert to bytes */
1404 } else { /* BB improve the check for buffer overruns BB */
1405 name_len = strnlen(fromName, PATH_MAX);
1406 name_len++; /* trailing null */
1407 strncpy(pSMB->OldFileName, fromName, name_len);
1408 name_len2 = strnlen(toName, PATH_MAX);
1409 name_len2++; /* trailing null */
1410 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1411 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1412 name_len2++; /* trailing null */
1413 name_len2++; /* signature byte */
1416 count = 1 /* 1st signature byte */ + name_len + name_len2;
1417 pSMB->hdr.smb_buf_length += count;
1418 pSMB->ByteCount = cpu_to_le16(count);
1420 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1421 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1422 cifs_stats_inc(&tcon->num_renames);
1424 cFYI(1, ("Send error in rename = %d", rc));
1427 cifs_buf_release(pSMB);
1435 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1436 int netfid, char * target_name,
1437 const struct nls_table * nls_codepage, int remap)
1439 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1440 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1441 struct set_file_rename * rename_info;
1443 char dummy_string[30];
1445 int bytes_returned = 0;
1447 __u16 params, param_offset, offset, count, byte_count;
1449 cFYI(1, ("Rename to File by handle"));
1450 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1456 pSMB->MaxSetupCount = 0;
1460 pSMB->Reserved2 = 0;
1461 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1462 offset = param_offset + params;
1464 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1465 rename_info = (struct set_file_rename *) data_offset;
1466 pSMB->MaxParameterCount = cpu_to_le16(2);
1467 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1468 pSMB->SetupCount = 1;
1469 pSMB->Reserved3 = 0;
1470 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1471 byte_count = 3 /* pad */ + params;
1472 pSMB->ParameterCount = cpu_to_le16(params);
1473 pSMB->TotalParameterCount = pSMB->ParameterCount;
1474 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1475 pSMB->DataOffset = cpu_to_le16(offset);
1476 /* construct random name ".cifs_tmp<inodenum><mid>" */
1477 rename_info->overwrite = cpu_to_le32(1);
1478 rename_info->root_fid = 0;
1479 /* unicode only call */
1480 if(target_name == NULL) {
1481 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1482 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1483 dummy_string, 24, nls_codepage, remap);
1485 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1486 target_name, PATH_MAX, nls_codepage, remap);
1488 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1489 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1490 byte_count += count;
1491 pSMB->DataCount = cpu_to_le16(count);
1492 pSMB->TotalDataCount = pSMB->DataCount;
1494 pSMB->InformationLevel =
1495 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1496 pSMB->Reserved4 = 0;
1497 pSMB->hdr.smb_buf_length += byte_count;
1498 pSMB->ByteCount = cpu_to_le16(byte_count);
1499 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1501 cifs_stats_inc(&pTcon->num_t2renames);
1503 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1506 cifs_buf_release(pSMB);
1508 /* Note: On -EAGAIN error only caller can retry on handle based calls
1509 since file handle passed in no longer valid */
1515 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1516 const __u16 target_tid, const char *toName, const int flags,
1517 const struct nls_table *nls_codepage, int remap)
1520 COPY_REQ *pSMB = NULL;
1521 COPY_RSP *pSMBr = NULL;
1523 int name_len, name_len2;
1526 cFYI(1, ("In CIFSSMBCopy"));
1528 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1533 pSMB->BufferFormat = 0x04;
1534 pSMB->Tid2 = target_tid;
1536 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1538 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1539 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1540 fromName, PATH_MAX, nls_codepage,
1542 name_len++; /* trailing null */
1544 pSMB->OldFileName[name_len] = 0x04; /* pad */
1545 /* protocol requires ASCII signature byte on Unicode string */
1546 pSMB->OldFileName[name_len + 1] = 0x00;
1547 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1548 toName, PATH_MAX, nls_codepage, remap);
1549 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1550 name_len2 *= 2; /* convert to bytes */
1551 } else { /* BB improve the check for buffer overruns BB */
1552 name_len = strnlen(fromName, PATH_MAX);
1553 name_len++; /* trailing null */
1554 strncpy(pSMB->OldFileName, fromName, name_len);
1555 name_len2 = strnlen(toName, PATH_MAX);
1556 name_len2++; /* trailing null */
1557 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1558 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1559 name_len2++; /* trailing null */
1560 name_len2++; /* signature byte */
1563 count = 1 /* 1st signature byte */ + name_len + name_len2;
1564 pSMB->hdr.smb_buf_length += count;
1565 pSMB->ByteCount = cpu_to_le16(count);
1567 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1568 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1570 cFYI(1, ("Send error in copy = %d with %d files copied",
1571 rc, le16_to_cpu(pSMBr->CopyCount)));
1574 cifs_buf_release(pSMB);
1583 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1584 const char *fromName, const char *toName,
1585 const struct nls_table *nls_codepage)
1587 TRANSACTION2_SPI_REQ *pSMB = NULL;
1588 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1591 int name_len_target;
1593 int bytes_returned = 0;
1594 __u16 params, param_offset, offset, byte_count;
1596 cFYI(1, ("In Symlink Unix style"));
1598 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1603 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1605 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
1606 /* find define for this maxpathcomponent */
1608 name_len++; /* trailing null */
1611 } else { /* BB improve the check for buffer overruns BB */
1612 name_len = strnlen(fromName, PATH_MAX);
1613 name_len++; /* trailing null */
1614 strncpy(pSMB->FileName, fromName, name_len);
1616 params = 6 + name_len;
1617 pSMB->MaxSetupCount = 0;
1621 pSMB->Reserved2 = 0;
1622 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1623 InformationLevel) - 4;
1624 offset = param_offset + params;
1626 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1627 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1629 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
1630 /* find define for this maxpathcomponent */
1632 name_len_target++; /* trailing null */
1633 name_len_target *= 2;
1634 } else { /* BB improve the check for buffer overruns BB */
1635 name_len_target = strnlen(toName, PATH_MAX);
1636 name_len_target++; /* trailing null */
1637 strncpy(data_offset, toName, name_len_target);
1640 pSMB->MaxParameterCount = cpu_to_le16(2);
1641 /* BB find exact max on data count below from sess */
1642 pSMB->MaxDataCount = cpu_to_le16(1000);
1643 pSMB->SetupCount = 1;
1644 pSMB->Reserved3 = 0;
1645 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1646 byte_count = 3 /* pad */ + params + name_len_target;
1647 pSMB->DataCount = cpu_to_le16(name_len_target);
1648 pSMB->ParameterCount = cpu_to_le16(params);
1649 pSMB->TotalDataCount = pSMB->DataCount;
1650 pSMB->TotalParameterCount = pSMB->ParameterCount;
1651 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1652 pSMB->DataOffset = cpu_to_le16(offset);
1653 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1654 pSMB->Reserved4 = 0;
1655 pSMB->hdr.smb_buf_length += byte_count;
1656 pSMB->ByteCount = cpu_to_le16(byte_count);
1657 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1658 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1659 cifs_stats_inc(&tcon->num_symlinks);
1662 ("Send error in SetPathInfo (create symlink) = %d",
1667 cifs_buf_release(pSMB);
1670 goto createSymLinkRetry;
1676 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1677 const char *fromName, const char *toName,
1678 const struct nls_table *nls_codepage, int remap)
1680 TRANSACTION2_SPI_REQ *pSMB = NULL;
1681 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1684 int name_len_target;
1686 int bytes_returned = 0;
1687 __u16 params, param_offset, offset, byte_count;
1689 cFYI(1, ("In Create Hard link Unix style"));
1690 createHardLinkRetry:
1691 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1696 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1697 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1698 PATH_MAX, nls_codepage, remap);
1699 name_len++; /* trailing null */
1702 } else { /* BB improve the check for buffer overruns BB */
1703 name_len = strnlen(toName, PATH_MAX);
1704 name_len++; /* trailing null */
1705 strncpy(pSMB->FileName, toName, name_len);
1707 params = 6 + name_len;
1708 pSMB->MaxSetupCount = 0;
1712 pSMB->Reserved2 = 0;
1713 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1714 InformationLevel) - 4;
1715 offset = param_offset + params;
1717 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1718 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1720 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1721 nls_codepage, remap);
1722 name_len_target++; /* trailing null */
1723 name_len_target *= 2;
1724 } else { /* BB improve the check for buffer overruns BB */
1725 name_len_target = strnlen(fromName, PATH_MAX);
1726 name_len_target++; /* trailing null */
1727 strncpy(data_offset, fromName, name_len_target);
1730 pSMB->MaxParameterCount = cpu_to_le16(2);
1731 /* BB find exact max on data count below from sess*/
1732 pSMB->MaxDataCount = cpu_to_le16(1000);
1733 pSMB->SetupCount = 1;
1734 pSMB->Reserved3 = 0;
1735 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1736 byte_count = 3 /* pad */ + params + name_len_target;
1737 pSMB->ParameterCount = cpu_to_le16(params);
1738 pSMB->TotalParameterCount = pSMB->ParameterCount;
1739 pSMB->DataCount = cpu_to_le16(name_len_target);
1740 pSMB->TotalDataCount = pSMB->DataCount;
1741 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1742 pSMB->DataOffset = cpu_to_le16(offset);
1743 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1744 pSMB->Reserved4 = 0;
1745 pSMB->hdr.smb_buf_length += byte_count;
1746 pSMB->ByteCount = cpu_to_le16(byte_count);
1747 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1748 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1749 cifs_stats_inc(&tcon->num_hardlinks);
1751 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1754 cifs_buf_release(pSMB);
1756 goto createHardLinkRetry;
1762 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1763 const char *fromName, const char *toName,
1764 const struct nls_table *nls_codepage, int remap)
1767 NT_RENAME_REQ *pSMB = NULL;
1768 RENAME_RSP *pSMBr = NULL;
1770 int name_len, name_len2;
1773 cFYI(1, ("In CIFSCreateHardLink"));
1774 winCreateHardLinkRetry:
1776 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1781 pSMB->SearchAttributes =
1782 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1784 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1785 pSMB->ClusterCount = 0;
1787 pSMB->BufferFormat = 0x04;
1789 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1791 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1792 PATH_MAX, nls_codepage, remap);
1793 name_len++; /* trailing null */
1795 pSMB->OldFileName[name_len] = 0; /* pad */
1796 pSMB->OldFileName[name_len + 1] = 0x04;
1798 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1799 toName, PATH_MAX, nls_codepage, remap);
1800 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1801 name_len2 *= 2; /* convert to bytes */
1802 } else { /* BB improve the check for buffer overruns BB */
1803 name_len = strnlen(fromName, PATH_MAX);
1804 name_len++; /* trailing null */
1805 strncpy(pSMB->OldFileName, fromName, name_len);
1806 name_len2 = strnlen(toName, PATH_MAX);
1807 name_len2++; /* trailing null */
1808 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1809 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1810 name_len2++; /* trailing null */
1811 name_len2++; /* signature byte */
1814 count = 1 /* string type byte */ + name_len + name_len2;
1815 pSMB->hdr.smb_buf_length += count;
1816 pSMB->ByteCount = cpu_to_le16(count);
1818 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1819 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1820 cifs_stats_inc(&tcon->num_hardlinks);
1822 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1824 cifs_buf_release(pSMB);
1826 goto winCreateHardLinkRetry;
1832 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1833 const unsigned char *searchName,
1834 char *symlinkinfo, const int buflen,
1835 const struct nls_table *nls_codepage)
1837 /* SMB_QUERY_FILE_UNIX_LINK */
1838 TRANSACTION2_QPI_REQ *pSMB = NULL;
1839 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1843 __u16 params, byte_count;
1845 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1848 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1853 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1855 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
1856 /* find define for this maxpathcomponent */
1858 name_len++; /* trailing null */
1860 } else { /* BB improve the check for buffer overruns BB */
1861 name_len = strnlen(searchName, PATH_MAX);
1862 name_len++; /* trailing null */
1863 strncpy(pSMB->FileName, searchName, name_len);
1866 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1867 pSMB->TotalDataCount = 0;
1868 pSMB->MaxParameterCount = cpu_to_le16(2);
1869 /* BB find exact max data count below from sess structure BB */
1870 pSMB->MaxDataCount = cpu_to_le16(4000);
1871 pSMB->MaxSetupCount = 0;
1875 pSMB->Reserved2 = 0;
1876 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1877 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1878 pSMB->DataCount = 0;
1879 pSMB->DataOffset = 0;
1880 pSMB->SetupCount = 1;
1881 pSMB->Reserved3 = 0;
1882 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1883 byte_count = params + 1 /* pad */ ;
1884 pSMB->TotalParameterCount = cpu_to_le16(params);
1885 pSMB->ParameterCount = pSMB->TotalParameterCount;
1886 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1887 pSMB->Reserved4 = 0;
1888 pSMB->hdr.smb_buf_length += byte_count;
1889 pSMB->ByteCount = cpu_to_le16(byte_count);
1891 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1892 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1894 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1896 /* decode response */
1898 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1899 if (rc || (pSMBr->ByteCount < 2))
1900 /* BB also check enough total bytes returned */
1901 rc = -EIO; /* bad smb */
1903 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1904 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1906 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1907 name_len = UniStrnlen((wchar_t *) ((char *)
1908 &pSMBr->hdr.Protocol +data_offset),
1909 min_t(const int, buflen,count) / 2);
1910 /* BB FIXME investigate remapping reserved chars here */
1911 cifs_strfromUCS_le(symlinkinfo,
1912 (__le16 *) ((char *)&pSMBr->hdr.Protocol +
1914 name_len, nls_codepage);
1916 strncpy(symlinkinfo,
1917 (char *) &pSMBr->hdr.Protocol +
1919 min_t(const int, buflen, count));
1921 symlinkinfo[buflen] = 0;
1922 /* just in case so calling code does not go off the end of buffer */
1925 cifs_buf_release(pSMB);
1927 goto querySymLinkRetry;
1931 /* Initialize NT TRANSACT SMB into small smb request buffer.
1932 This assumes that all NT TRANSACTS that we init here have
1933 total parm and data under about 400 bytes (to fit in small cifs
1934 buffer size), which is the case so far, it easily fits. NB:
1935 Setup words themselves and ByteCount
1936 MaxSetupCount (size of returned setup area) and
1937 MaxParameterCount (returned parms size) must be set by caller */
1939 smb_init_ntransact(const __u16 sub_command, const int setup_count,
1940 const int parm_len, struct cifsTconInfo *tcon,
1945 struct smb_com_ntransact_req * pSMB;
1947 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
1951 *ret_buf = (void *)pSMB;
1953 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
1954 pSMB->TotalDataCount = 0;
1955 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
1956 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1957 pSMB->ParameterCount = pSMB->TotalParameterCount;
1958 pSMB->DataCount = pSMB->TotalDataCount;
1959 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
1960 (setup_count * 2) - 4 /* for rfc1001 length itself */;
1961 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
1962 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
1963 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
1964 pSMB->SubCommand = cpu_to_le16(sub_command);
1969 validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
1970 int * pdatalen, int * pparmlen)
1973 __u32 data_count, data_offset, parm_count, parm_offset;
1974 struct smb_com_ntransact_rsp * pSMBr;
1979 pSMBr = (struct smb_com_ntransact_rsp *)buf;
1981 /* ByteCount was converted from little endian in SendReceive */
1982 end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
1983 (char *)&pSMBr->ByteCount;
1986 data_offset = le32_to_cpu(pSMBr->DataOffset);
1987 data_count = le32_to_cpu(pSMBr->DataCount);
1988 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
1989 parm_count = le32_to_cpu(pSMBr->ParameterCount);
1991 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
1992 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
1994 /* should we also check that parm and data areas do not overlap? */
1995 if(*ppparm > end_of_smb) {
1996 cFYI(1,("parms start after end of smb"));
1998 } else if(parm_count + *ppparm > end_of_smb) {
1999 cFYI(1,("parm end after end of smb"));
2001 } else if(*ppdata > end_of_smb) {
2002 cFYI(1,("data starts after end of smb"));
2004 } else if(data_count + *ppdata > end_of_smb) {
2005 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
2006 *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
2008 } else if(parm_count + data_count > pSMBr->ByteCount) {
2009 cFYI(1,("parm count and data count larger than SMB"));
2016 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2017 const unsigned char *searchName,
2018 char *symlinkinfo, const int buflen,__u16 fid,
2019 const struct nls_table *nls_codepage)
2024 struct smb_com_transaction_ioctl_req * pSMB;
2025 struct smb_com_transaction_ioctl_rsp * pSMBr;
2027 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2028 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2033 pSMB->TotalParameterCount = 0 ;
2034 pSMB->TotalDataCount = 0;
2035 pSMB->MaxParameterCount = cpu_to_le32(2);
2036 /* BB find exact data count max from sess structure BB */
2037 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2038 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2039 pSMB->MaxSetupCount = 4;
2041 pSMB->ParameterOffset = 0;
2042 pSMB->DataCount = 0;
2043 pSMB->DataOffset = 0;
2044 pSMB->SetupCount = 4;
2045 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2046 pSMB->ParameterCount = pSMB->TotalParameterCount;
2047 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2048 pSMB->IsFsctl = 1; /* FSCTL */
2049 pSMB->IsRootFlag = 0;
2050 pSMB->Fid = fid; /* file handle always le */
2051 pSMB->ByteCount = 0;
2053 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2054 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2056 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2057 } else { /* decode response */
2058 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2059 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2060 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2061 /* BB also check enough total bytes returned */
2062 rc = -EIO; /* bad smb */
2064 if(data_count && (data_count < 2048)) {
2065 char * end_of_smb = 2 /* sizeof byte count */ +
2067 (char *)&pSMBr->ByteCount;
2069 struct reparse_data * reparse_buf = (struct reparse_data *)
2070 ((char *)&pSMBr->hdr.Protocol + data_offset);
2071 if((char*)reparse_buf >= end_of_smb) {
2075 if((reparse_buf->LinkNamesBuf +
2076 reparse_buf->TargetNameOffset +
2077 reparse_buf->TargetNameLen) >
2079 cFYI(1,("reparse buf extended beyond SMB"));
2084 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2085 name_len = UniStrnlen((wchar_t *)
2086 (reparse_buf->LinkNamesBuf +
2087 reparse_buf->TargetNameOffset),
2088 min(buflen/2, reparse_buf->TargetNameLen / 2));
2089 cifs_strfromUCS_le(symlinkinfo,
2090 (__le16 *) (reparse_buf->LinkNamesBuf +
2091 reparse_buf->TargetNameOffset),
2092 name_len, nls_codepage);
2093 } else { /* ASCII names */
2094 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
2095 reparse_buf->TargetNameOffset,
2096 min_t(const int, buflen, reparse_buf->TargetNameLen));
2100 cFYI(1,("Invalid return data count on get reparse info ioctl"));
2102 symlinkinfo[buflen] = 0; /* just in case so the caller
2103 does not go off the end of the buffer */
2104 cFYI(1,("readlink result - %s ",symlinkinfo));
2108 cifs_buf_release(pSMB);
2110 /* Note: On -EAGAIN error only caller can retry on handle based calls
2111 since file handle passed in no longer valid */
2116 #ifdef CONFIG_CIFS_POSIX
2118 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2119 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
2121 /* u8 cifs fields do not need le conversion */
2122 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2123 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2124 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2125 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2130 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2131 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
2132 const int acl_type,const int size_of_data_area)
2137 struct cifs_posix_ace * pACE;
2138 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
2139 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
2141 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2144 if(acl_type & ACL_TYPE_ACCESS) {
2145 count = le16_to_cpu(cifs_acl->access_entry_count);
2146 pACE = &cifs_acl->ace_array[0];
2147 size = sizeof(struct cifs_posix_acl);
2148 size += sizeof(struct cifs_posix_ace) * count;
2149 /* check if we would go beyond end of SMB */
2150 if(size_of_data_area < size) {
2151 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2154 } else if(acl_type & ACL_TYPE_DEFAULT) {
2155 count = le16_to_cpu(cifs_acl->access_entry_count);
2156 size = sizeof(struct cifs_posix_acl);
2157 size += sizeof(struct cifs_posix_ace) * count;
2158 /* skip past access ACEs to get to default ACEs */
2159 pACE = &cifs_acl->ace_array[count];
2160 count = le16_to_cpu(cifs_acl->default_entry_count);
2161 size += sizeof(struct cifs_posix_ace) * count;
2162 /* check if we would go beyond end of SMB */
2163 if(size_of_data_area < size)
2170 size = posix_acl_xattr_size(count);
2171 if((buflen == 0) || (local_acl == NULL)) {
2172 /* used to query ACL EA size */
2173 } else if(size > buflen) {
2175 } else /* buffer big enough */ {
2176 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2177 for(i = 0;i < count ;i++) {
2178 cifs_convert_ace(&local_acl->a_entries[i],pACE);
2185 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2186 const posix_acl_xattr_entry * local_ace)
2188 __u16 rc = 0; /* 0 = ACL converted ok */
2190 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2191 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2192 /* BB is there a better way to handle the large uid? */
2193 if(local_ace->e_id == cpu_to_le32(-1)) {
2194 /* Probably no need to le convert -1 on any arch but can not hurt */
2195 cifs_ace->cifs_uid = cpu_to_le64(-1);
2197 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2198 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2202 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2203 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2207 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2208 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2212 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2215 count = posix_acl_xattr_count((size_t)buflen);
2216 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2217 count, buflen, le32_to_cpu(local_acl->a_version)));
2218 if(le32_to_cpu(local_acl->a_version) != 2) {
2219 cFYI(1,("unknown POSIX ACL version %d",
2220 le32_to_cpu(local_acl->a_version)));
2223 cifs_acl->version = cpu_to_le16(1);
2224 if(acl_type == ACL_TYPE_ACCESS)
2225 cifs_acl->access_entry_count = cpu_to_le16(count);
2226 else if(acl_type == ACL_TYPE_DEFAULT)
2227 cifs_acl->default_entry_count = cpu_to_le16(count);
2229 cFYI(1,("unknown ACL type %d",acl_type));
2232 for(i=0;i<count;i++) {
2233 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2234 &local_acl->a_entries[i]);
2236 /* ACE not converted */
2241 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2242 rc += sizeof(struct cifs_posix_acl);
2243 /* BB add check to make sure ACL does not overflow SMB */
2249 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2250 const unsigned char *searchName,
2251 char *acl_inf, const int buflen, const int acl_type,
2252 const struct nls_table *nls_codepage, int remap)
2254 /* SMB_QUERY_POSIX_ACL */
2255 TRANSACTION2_QPI_REQ *pSMB = NULL;
2256 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2260 __u16 params, byte_count;
2262 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2265 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2270 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2272 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2273 PATH_MAX, nls_codepage, remap);
2274 name_len++; /* trailing null */
2276 pSMB->FileName[name_len] = 0;
2277 pSMB->FileName[name_len+1] = 0;
2278 } else { /* BB improve the check for buffer overruns BB */
2279 name_len = strnlen(searchName, PATH_MAX);
2280 name_len++; /* trailing null */
2281 strncpy(pSMB->FileName, searchName, name_len);
2284 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2285 pSMB->TotalDataCount = 0;
2286 pSMB->MaxParameterCount = cpu_to_le16(2);
2287 /* BB find exact max data count below from sess structure BB */
2288 pSMB->MaxDataCount = cpu_to_le16(4000);
2289 pSMB->MaxSetupCount = 0;
2293 pSMB->Reserved2 = 0;
2294 pSMB->ParameterOffset = cpu_to_le16(
2295 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2296 pSMB->DataCount = 0;
2297 pSMB->DataOffset = 0;
2298 pSMB->SetupCount = 1;
2299 pSMB->Reserved3 = 0;
2300 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2301 byte_count = params + 1 /* pad */ ;
2302 pSMB->TotalParameterCount = cpu_to_le16(params);
2303 pSMB->ParameterCount = pSMB->TotalParameterCount;
2304 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2305 pSMB->Reserved4 = 0;
2306 pSMB->hdr.smb_buf_length += byte_count;
2307 pSMB->ByteCount = cpu_to_le16(byte_count);
2309 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2310 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2311 cifs_stats_inc(&tcon->num_acl_get);
2313 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2315 /* decode response */
2317 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2318 if (rc || (pSMBr->ByteCount < 2))
2319 /* BB also check enough total bytes returned */
2320 rc = -EIO; /* bad smb */
2322 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2323 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2324 rc = cifs_copy_posix_acl(acl_inf,
2325 (char *)&pSMBr->hdr.Protocol+data_offset,
2326 buflen,acl_type,count);
2329 cifs_buf_release(pSMB);
2336 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2337 const unsigned char *fileName,
2338 const char *local_acl, const int buflen,
2340 const struct nls_table *nls_codepage, int remap)
2342 struct smb_com_transaction2_spi_req *pSMB = NULL;
2343 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2347 int bytes_returned = 0;
2348 __u16 params, byte_count, data_count, param_offset, offset;
2350 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2352 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2356 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2358 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2359 PATH_MAX, nls_codepage, remap);
2360 name_len++; /* trailing null */
2362 } else { /* BB improve the check for buffer overruns BB */
2363 name_len = strnlen(fileName, PATH_MAX);
2364 name_len++; /* trailing null */
2365 strncpy(pSMB->FileName, fileName, name_len);
2367 params = 6 + name_len;
2368 pSMB->MaxParameterCount = cpu_to_le16(2);
2369 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2370 pSMB->MaxSetupCount = 0;
2374 pSMB->Reserved2 = 0;
2375 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2376 InformationLevel) - 4;
2377 offset = param_offset + params;
2378 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2379 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2381 /* convert to on the wire format for POSIX ACL */
2382 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2384 if(data_count == 0) {
2386 goto setACLerrorExit;
2388 pSMB->DataOffset = cpu_to_le16(offset);
2389 pSMB->SetupCount = 1;
2390 pSMB->Reserved3 = 0;
2391 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2392 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2393 byte_count = 3 /* pad */ + params + data_count;
2394 pSMB->DataCount = cpu_to_le16(data_count);
2395 pSMB->TotalDataCount = pSMB->DataCount;
2396 pSMB->ParameterCount = cpu_to_le16(params);
2397 pSMB->TotalParameterCount = pSMB->ParameterCount;
2398 pSMB->Reserved4 = 0;
2399 pSMB->hdr.smb_buf_length += byte_count;
2400 pSMB->ByteCount = cpu_to_le16(byte_count);
2401 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2402 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2404 cFYI(1, ("Set POSIX ACL returned %d", rc));
2408 cifs_buf_release(pSMB);
2414 /* BB fix tabs in this function FIXME BB */
2416 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2417 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2420 struct smb_t2_qfi_req *pSMB = NULL;
2421 struct smb_t2_qfi_rsp *pSMBr = NULL;
2423 __u16 params, byte_count;
2425 cFYI(1,("In GetExtAttr"));
2430 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2435 params = 2 /* level */ +2 /* fid */;
2436 pSMB->t2.TotalDataCount = 0;
2437 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2438 /* BB find exact max data count below from sess structure BB */
2439 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2440 pSMB->t2.MaxSetupCount = 0;
2441 pSMB->t2.Reserved = 0;
2443 pSMB->t2.Timeout = 0;
2444 pSMB->t2.Reserved2 = 0;
2445 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2447 pSMB->t2.DataCount = 0;
2448 pSMB->t2.DataOffset = 0;
2449 pSMB->t2.SetupCount = 1;
2450 pSMB->t2.Reserved3 = 0;
2451 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2452 byte_count = params + 1 /* pad */ ;
2453 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2454 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2455 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2458 pSMB->hdr.smb_buf_length += byte_count;
2459 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2461 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2462 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2464 cFYI(1, ("error %d in GetExtAttr", rc));
2466 /* decode response */
2467 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2468 if (rc || (pSMBr->ByteCount < 2))
2469 /* BB also check enough total bytes returned */
2470 /* If rc should we check for EOPNOSUPP and
2471 disable the srvino flag? or in caller? */
2472 rc = -EIO; /* bad smb */
2474 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2475 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2476 struct file_chattr_info * pfinfo;
2477 /* BB Do we need a cast or hash here ? */
2479 cFYI(1, ("Illegal size ret in GetExtAttr"));
2483 pfinfo = (struct file_chattr_info *)
2484 (data_offset + (char *) &pSMBr->hdr.Protocol);
2485 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2486 *pMask = le64_to_cpu(pfinfo->mask);
2490 cifs_buf_release(pSMB);
2492 goto GetExtAttrRetry;
2497 #endif /* CONFIG_POSIX */
2500 /* security id for everyone */
2501 const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
2503 const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
2505 /* Convert CIFS ACL to POSIX form */
2506 static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
2511 /* Get Security Descriptor (by handle) from remote server for a file or dir */
2513 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
2514 /* BB fix up return info */ char *acl_inf, const int buflen,
2515 const int acl_type /* ACCESS/DEFAULT not sure implication */)
2519 QUERY_SEC_DESC_REQ * pSMB;
2522 cFYI(1, ("GetCifsACL"));
2524 rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
2525 8 /* parm len */, tcon, (void **) &pSMB);
2529 pSMB->MaxParameterCount = cpu_to_le32(4);
2530 /* BB TEST with big acls that might need to be e.g. larger than 16K */
2531 pSMB->MaxSetupCount = 0;
2532 pSMB->Fid = fid; /* file handle always le */
2533 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
2535 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
2536 pSMB->hdr.smb_buf_length += 11;
2537 iov[0].iov_base = (char *)pSMB;
2538 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
2540 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
2541 cifs_stats_inc(&tcon->num_acl_get);
2543 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
2544 } else { /* decode response */
2545 struct cifs_sid * psec_desc;
2550 struct smb_com_ntransact_rsp * pSMBr;
2552 /* validate_nttransact */
2553 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
2554 (char **)&psec_desc,
2555 &parm_len, &data_len);
2559 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
2561 cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
2563 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
2564 rc = -EIO; /* bad smb */
2568 /* BB check that data area is minimum length and as big as acl_len */
2570 acl_len = le32_to_cpu(*(__le32 *)parm);
2571 /* BB check if(acl_len > bufsize) */
2573 parse_sec_desc(psec_desc, acl_len);
2576 if(buf_type == CIFS_SMALL_BUFFER)
2577 cifs_small_buf_release(iov[0].iov_base);
2578 else if(buf_type == CIFS_LARGE_BUFFER)
2579 cifs_buf_release(iov[0].iov_base);
2580 cifs_small_buf_release(pSMB);
2585 /* Legacy Query Path Information call for lookup to old servers such
2587 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2588 const unsigned char *searchName,
2589 FILE_ALL_INFO * pFinfo,
2590 const struct nls_table *nls_codepage, int remap)
2592 QUERY_INFORMATION_REQ * pSMB;
2593 QUERY_INFORMATION_RSP * pSMBr;
2598 cFYI(1, ("In SMBQPath path %s", searchName));
2600 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2605 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2607 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2608 PATH_MAX, nls_codepage, remap);
2609 name_len++; /* trailing null */
2612 name_len = strnlen(searchName, PATH_MAX);
2613 name_len++; /* trailing null */
2614 strncpy(pSMB->FileName, searchName, name_len);
2616 pSMB->BufferFormat = 0x04;
2617 name_len++; /* account for buffer type byte */
2618 pSMB->hdr.smb_buf_length += (__u16) name_len;
2619 pSMB->ByteCount = cpu_to_le16(name_len);
2621 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2622 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2624 cFYI(1, ("Send error in QueryInfo = %d", rc));
2625 } else if (pFinfo) { /* decode response */
2626 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2627 pFinfo->AllocationSize =
2628 cpu_to_le64(le32_to_cpu(pSMBr->size));
2629 pFinfo->EndOfFile = pFinfo->AllocationSize;
2630 pFinfo->Attributes =
2631 cpu_to_le32(le16_to_cpu(pSMBr->attr));
2633 rc = -EIO; /* bad buffer passed in */
2635 cifs_buf_release(pSMB);
2647 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2648 const unsigned char *searchName,
2649 FILE_ALL_INFO * pFindData,
2650 const struct nls_table *nls_codepage, int remap)
2652 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2653 TRANSACTION2_QPI_REQ *pSMB = NULL;
2654 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2658 __u16 params, byte_count;
2660 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2662 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2667 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2669 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2670 PATH_MAX, nls_codepage, remap);
2671 name_len++; /* trailing null */
2673 } else { /* BB improve the check for buffer overruns BB */
2674 name_len = strnlen(searchName, PATH_MAX);
2675 name_len++; /* trailing null */
2676 strncpy(pSMB->FileName, searchName, name_len);
2679 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2680 pSMB->TotalDataCount = 0;
2681 pSMB->MaxParameterCount = cpu_to_le16(2);
2682 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2683 pSMB->MaxSetupCount = 0;
2687 pSMB->Reserved2 = 0;
2688 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2689 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2690 pSMB->DataCount = 0;
2691 pSMB->DataOffset = 0;
2692 pSMB->SetupCount = 1;
2693 pSMB->Reserved3 = 0;
2694 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2695 byte_count = params + 1 /* pad */ ;
2696 pSMB->TotalParameterCount = cpu_to_le16(params);
2697 pSMB->ParameterCount = pSMB->TotalParameterCount;
2698 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2699 pSMB->Reserved4 = 0;
2700 pSMB->hdr.smb_buf_length += byte_count;
2701 pSMB->ByteCount = cpu_to_le16(byte_count);
2703 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2704 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2706 cFYI(1, ("Send error in QPathInfo = %d", rc));
2707 } else { /* decode response */
2708 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2710 if (rc || (pSMBr->ByteCount < 40))
2711 rc = -EIO; /* bad smb */
2712 else if (pFindData){
2713 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2714 memcpy((char *) pFindData,
2715 (char *) &pSMBr->hdr.Protocol +
2716 data_offset, sizeof (FILE_ALL_INFO));
2720 cifs_buf_release(pSMB);
2722 goto QPathInfoRetry;
2728 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2729 const unsigned char *searchName,
2730 FILE_UNIX_BASIC_INFO * pFindData,
2731 const struct nls_table *nls_codepage, int remap)
2733 /* SMB_QUERY_FILE_UNIX_BASIC */
2734 TRANSACTION2_QPI_REQ *pSMB = NULL;
2735 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2737 int bytes_returned = 0;
2739 __u16 params, byte_count;
2741 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2743 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2748 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2750 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2751 PATH_MAX, nls_codepage, remap);
2752 name_len++; /* trailing null */
2754 } else { /* BB improve the check for buffer overruns BB */
2755 name_len = strnlen(searchName, PATH_MAX);
2756 name_len++; /* trailing null */
2757 strncpy(pSMB->FileName, searchName, name_len);
2760 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2761 pSMB->TotalDataCount = 0;
2762 pSMB->MaxParameterCount = cpu_to_le16(2);
2763 /* BB find exact max SMB PDU from sess structure BB */
2764 pSMB->MaxDataCount = cpu_to_le16(4000);
2765 pSMB->MaxSetupCount = 0;
2769 pSMB->Reserved2 = 0;
2770 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2771 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2772 pSMB->DataCount = 0;
2773 pSMB->DataOffset = 0;
2774 pSMB->SetupCount = 1;
2775 pSMB->Reserved3 = 0;
2776 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2777 byte_count = params + 1 /* pad */ ;
2778 pSMB->TotalParameterCount = cpu_to_le16(params);
2779 pSMB->ParameterCount = pSMB->TotalParameterCount;
2780 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2781 pSMB->Reserved4 = 0;
2782 pSMB->hdr.smb_buf_length += byte_count;
2783 pSMB->ByteCount = cpu_to_le16(byte_count);
2785 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2786 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2788 cFYI(1, ("Send error in QPathInfo = %d", rc));
2789 } else { /* decode response */
2790 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2792 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2793 rc = -EIO; /* bad smb */
2795 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2796 memcpy((char *) pFindData,
2797 (char *) &pSMBr->hdr.Protocol +
2799 sizeof (FILE_UNIX_BASIC_INFO));
2802 cifs_buf_release(pSMB);
2804 goto UnixQPathInfoRetry;
2809 #if 0 /* function unused at present */
2810 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2811 const char *searchName, FILE_ALL_INFO * findData,
2812 const struct nls_table *nls_codepage)
2814 /* level 257 SMB_ */
2815 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2816 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2820 __u16 params, byte_count;
2822 cFYI(1, ("In FindUnique"));
2824 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2829 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2831 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2832 /* find define for this maxpathcomponent */
2834 name_len++; /* trailing null */
2836 } else { /* BB improve the check for buffer overruns BB */
2837 name_len = strnlen(searchName, PATH_MAX);
2838 name_len++; /* trailing null */
2839 strncpy(pSMB->FileName, searchName, name_len);
2842 params = 12 + name_len /* includes null */ ;
2843 pSMB->TotalDataCount = 0; /* no EAs */
2844 pSMB->MaxParameterCount = cpu_to_le16(2);
2845 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2846 pSMB->MaxSetupCount = 0;
2850 pSMB->Reserved2 = 0;
2851 pSMB->ParameterOffset = cpu_to_le16(
2852 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2853 pSMB->DataCount = 0;
2854 pSMB->DataOffset = 0;
2855 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2856 pSMB->Reserved3 = 0;
2857 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2858 byte_count = params + 1 /* pad */ ;
2859 pSMB->TotalParameterCount = cpu_to_le16(params);
2860 pSMB->ParameterCount = pSMB->TotalParameterCount;
2861 pSMB->SearchAttributes =
2862 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2864 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2865 pSMB->SearchFlags = cpu_to_le16(1);
2866 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2867 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2868 pSMB->hdr.smb_buf_length += byte_count;
2869 pSMB->ByteCount = cpu_to_le16(byte_count);
2871 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2872 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2875 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2876 } else { /* decode response */
2877 cifs_stats_inc(&tcon->num_ffirst);
2881 cifs_buf_release(pSMB);
2883 goto findUniqueRetry;
2887 #endif /* end unused (temporarily) function */
2889 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2891 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2892 const char *searchName,
2893 const struct nls_table *nls_codepage,
2895 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2897 /* level 257 SMB_ */
2898 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2899 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2900 T2_FFIRST_RSP_PARMS * parms;
2902 int bytes_returned = 0;
2904 __u16 params, byte_count;
2906 cFYI(1, ("In FindFirst for %s",searchName));
2909 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2914 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2916 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2917 PATH_MAX, nls_codepage, remap);
2918 /* We can not add the asterik earlier in case
2919 it got remapped to 0xF03A as if it were part of the
2920 directory name instead of a wildcard */
2922 pSMB->FileName[name_len] = dirsep;
2923 pSMB->FileName[name_len+1] = 0;
2924 pSMB->FileName[name_len+2] = '*';
2925 pSMB->FileName[name_len+3] = 0;
2926 name_len += 4; /* now the trailing null */
2927 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2928 pSMB->FileName[name_len+1] = 0;
2930 } else { /* BB add check for overrun of SMB buf BB */
2931 name_len = strnlen(searchName, PATH_MAX);
2932 /* BB fix here and in unicode clause above ie
2933 if(name_len > buffersize-header)
2934 free buffer exit; BB */
2935 strncpy(pSMB->FileName, searchName, name_len);
2936 pSMB->FileName[name_len] = dirsep;
2937 pSMB->FileName[name_len+1] = '*';
2938 pSMB->FileName[name_len+2] = 0;
2942 params = 12 + name_len /* includes null */ ;
2943 pSMB->TotalDataCount = 0; /* no EAs */
2944 pSMB->MaxParameterCount = cpu_to_le16(10);
2945 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2946 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2947 pSMB->MaxSetupCount = 0;
2951 pSMB->Reserved2 = 0;
2952 byte_count = params + 1 /* pad */ ;
2953 pSMB->TotalParameterCount = cpu_to_le16(params);
2954 pSMB->ParameterCount = pSMB->TotalParameterCount;
2955 pSMB->ParameterOffset = cpu_to_le16(
2956 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2957 pSMB->DataCount = 0;
2958 pSMB->DataOffset = 0;
2959 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2960 pSMB->Reserved3 = 0;
2961 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2962 pSMB->SearchAttributes =
2963 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2965 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2966 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2967 CIFS_SEARCH_RETURN_RESUME);
2968 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2970 /* BB what should we set StorageType to? Does it matter? BB */
2971 pSMB->SearchStorageType = 0;
2972 pSMB->hdr.smb_buf_length += byte_count;
2973 pSMB->ByteCount = cpu_to_le16(byte_count);
2975 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2976 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2977 cifs_stats_inc(&tcon->num_ffirst);
2979 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2980 /* BB Add code to handle unsupported level rc */
2981 cFYI(1, ("Error in FindFirst = %d", rc));
2984 cifs_buf_release(pSMB);
2986 /* BB eventually could optimize out free and realloc of buf */
2989 goto findFirstRetry;
2990 } else { /* decode response */
2991 /* BB remember to free buffer if error BB */
2992 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2994 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2995 psrch_inf->unicode = TRUE;
2997 psrch_inf->unicode = FALSE;
2999 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3000 psrch_inf->srch_entries_start =
3001 (char *) &pSMBr->hdr.Protocol +
3002 le16_to_cpu(pSMBr->t2.DataOffset);
3003 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3004 le16_to_cpu(pSMBr->t2.ParameterOffset));
3006 if(parms->EndofSearch)
3007 psrch_inf->endOfSearch = TRUE;
3009 psrch_inf->endOfSearch = FALSE;
3011 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3012 psrch_inf->index_of_last_entry =
3013 psrch_inf->entries_in_buffer;
3014 *pnetfid = parms->SearchHandle;
3016 cifs_buf_release(pSMB);
3023 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3024 __u16 searchHandle, struct cifs_search_info * psrch_inf)
3026 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3027 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3028 T2_FNEXT_RSP_PARMS * parms;
3029 char *response_data;
3031 int bytes_returned, name_len;
3032 __u16 params, byte_count;
3034 cFYI(1, ("In FindNext"));
3036 if(psrch_inf->endOfSearch == TRUE)
3039 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3044 params = 14; /* includes 2 bytes of null string, converted to LE below */
3046 pSMB->TotalDataCount = 0; /* no EAs */
3047 pSMB->MaxParameterCount = cpu_to_le16(8);
3048 pSMB->MaxDataCount =
3049 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3050 pSMB->MaxSetupCount = 0;
3054 pSMB->Reserved2 = 0;
3055 pSMB->ParameterOffset = cpu_to_le16(
3056 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3057 pSMB->DataCount = 0;
3058 pSMB->DataOffset = 0;
3059 pSMB->SetupCount = 1;
3060 pSMB->Reserved3 = 0;
3061 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3062 pSMB->SearchHandle = searchHandle; /* always kept as le */
3064 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
3065 /* test for Unix extensions */
3066 /* if (tcon->ses->capabilities & CAP_UNIX) {
3067 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
3068 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
3070 pSMB->InformationLevel =
3071 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
3072 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
3074 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3075 pSMB->ResumeKey = psrch_inf->resume_key;
3077 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3079 name_len = psrch_inf->resume_name_len;
3081 if(name_len < PATH_MAX) {
3082 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3083 byte_count += name_len;
3084 /* 14 byte parm len above enough for 2 byte null terminator */
3085 pSMB->ResumeFileName[name_len] = 0;
3086 pSMB->ResumeFileName[name_len+1] = 0;
3089 goto FNext2_err_exit;
3091 byte_count = params + 1 /* pad */ ;
3092 pSMB->TotalParameterCount = cpu_to_le16(params);
3093 pSMB->ParameterCount = pSMB->TotalParameterCount;
3094 pSMB->hdr.smb_buf_length += byte_count;
3095 pSMB->ByteCount = cpu_to_le16(byte_count);
3097 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3098 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3099 cifs_stats_inc(&tcon->num_fnext);
3102 psrch_inf->endOfSearch = TRUE;
3103 rc = 0; /* search probably was closed at end of search above */
3105 cFYI(1, ("FindNext returned = %d", rc));
3106 } else { /* decode response */
3107 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3110 /* BB fixme add lock for file (srch_info) struct here */
3111 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3112 psrch_inf->unicode = TRUE;
3114 psrch_inf->unicode = FALSE;
3115 response_data = (char *) &pSMBr->hdr.Protocol +
3116 le16_to_cpu(pSMBr->t2.ParameterOffset);
3117 parms = (T2_FNEXT_RSP_PARMS *)response_data;
3118 response_data = (char *)&pSMBr->hdr.Protocol +
3119 le16_to_cpu(pSMBr->t2.DataOffset);
3120 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3121 psrch_inf->srch_entries_start = response_data;
3122 psrch_inf->ntwrk_buf_start = (char *)pSMB;
3123 if(parms->EndofSearch)
3124 psrch_inf->endOfSearch = TRUE;
3126 psrch_inf->endOfSearch = FALSE;
3128 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
3129 psrch_inf->index_of_last_entry +=
3130 psrch_inf->entries_in_buffer;
3131 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
3133 /* BB fixme add unlock here */
3138 /* BB On error, should we leave previous search buf (and count and
3139 last entry fields) intact or free the previous one? */
3141 /* Note: On -EAGAIN error only caller can retry on handle based calls
3142 since file handle passed in no longer valid */
3145 cifs_buf_release(pSMB);
3151 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
3154 FINDCLOSE_REQ *pSMB = NULL;
3155 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
3158 cFYI(1, ("In CIFSSMBFindClose"));
3159 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3161 /* no sense returning error if session restarted
3162 as file handle has been closed */
3168 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
3169 pSMB->FileID = searchHandle;
3170 pSMB->ByteCount = 0;
3171 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3172 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3174 cERROR(1, ("Send error in FindClose = %d", rc));
3176 cifs_stats_inc(&tcon->num_fclose);
3177 cifs_small_buf_release(pSMB);
3179 /* Since session is dead, search handle closed on server already */
3187 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3188 const unsigned char *searchName,
3189 __u64 * inode_number,
3190 const struct nls_table *nls_codepage, int remap)
3193 TRANSACTION2_QPI_REQ *pSMB = NULL;
3194 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3195 int name_len, bytes_returned;
3196 __u16 params, byte_count;
3198 cFYI(1,("In GetSrvInodeNum for %s",searchName));
3202 GetInodeNumberRetry:
3203 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3209 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3211 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3212 PATH_MAX,nls_codepage, remap);
3213 name_len++; /* trailing null */
3215 } else { /* BB improve the check for buffer overruns BB */
3216 name_len = strnlen(searchName, PATH_MAX);
3217 name_len++; /* trailing null */
3218 strncpy(pSMB->FileName, searchName, name_len);
3221 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3222 pSMB->TotalDataCount = 0;
3223 pSMB->MaxParameterCount = cpu_to_le16(2);
3224 /* BB find exact max data count below from sess structure BB */
3225 pSMB->MaxDataCount = cpu_to_le16(4000);
3226 pSMB->MaxSetupCount = 0;
3230 pSMB->Reserved2 = 0;
3231 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3232 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3233 pSMB->DataCount = 0;
3234 pSMB->DataOffset = 0;
3235 pSMB->SetupCount = 1;
3236 pSMB->Reserved3 = 0;
3237 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3238 byte_count = params + 1 /* pad */ ;
3239 pSMB->TotalParameterCount = cpu_to_le16(params);
3240 pSMB->ParameterCount = pSMB->TotalParameterCount;
3241 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3242 pSMB->Reserved4 = 0;
3243 pSMB->hdr.smb_buf_length += byte_count;
3244 pSMB->ByteCount = cpu_to_le16(byte_count);
3246 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3247 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3249 cFYI(1, ("error %d in QueryInternalInfo", rc));
3251 /* decode response */
3252 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3253 if (rc || (pSMBr->ByteCount < 2))
3254 /* BB also check enough total bytes returned */
3255 /* If rc should we check for EOPNOSUPP and
3256 disable the srvino flag? or in caller? */
3257 rc = -EIO; /* bad smb */
3259 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3260 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3261 struct file_internal_info * pfinfo;
3262 /* BB Do we need a cast or hash here ? */
3264 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3266 goto GetInodeNumOut;
3268 pfinfo = (struct file_internal_info *)
3269 (data_offset + (char *) &pSMBr->hdr.Protocol);
3270 *inode_number = pfinfo->UniqueId;
3274 cifs_buf_release(pSMB);
3276 goto GetInodeNumberRetry;
3281 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3282 const unsigned char *searchName,
3283 unsigned char **targetUNCs,
3284 unsigned int *number_of_UNC_in_array,
3285 const struct nls_table *nls_codepage, int remap)
3287 /* TRANS2_GET_DFS_REFERRAL */
3288 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3289 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3290 struct dfs_referral_level_3 * referrals = NULL;
3296 __u16 params, byte_count;
3297 *number_of_UNC_in_array = 0;
3300 cFYI(1, ("In GetDFSRefer the path %s", searchName));
3304 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3309 /* server pointer checked in called function,
3310 but should never be null here anyway */
3311 pSMB->hdr.Mid = GetNextMid(ses->server);
3312 pSMB->hdr.Tid = ses->ipc_tid;
3313 pSMB->hdr.Uid = ses->Suid;
3314 if (ses->capabilities & CAP_STATUS32) {
3315 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3317 if (ses->capabilities & CAP_DFS) {
3318 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3321 if (ses->capabilities & CAP_UNICODE) {
3322 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3324 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3325 searchName, PATH_MAX, nls_codepage, remap);
3326 name_len++; /* trailing null */
3328 } else { /* BB improve the check for buffer overruns BB */
3329 name_len = strnlen(searchName, PATH_MAX);
3330 name_len++; /* trailing null */
3331 strncpy(pSMB->RequestFileName, searchName, name_len);
3334 params = 2 /* level */ + name_len /*includes null */ ;
3335 pSMB->TotalDataCount = 0;
3336 pSMB->DataCount = 0;
3337 pSMB->DataOffset = 0;
3338 pSMB->MaxParameterCount = 0;
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(offsetof(
3346 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3347 pSMB->SetupCount = 1;
3348 pSMB->Reserved3 = 0;
3349 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3350 byte_count = params + 3 /* pad */ ;
3351 pSMB->ParameterCount = cpu_to_le16(params);
3352 pSMB->TotalParameterCount = pSMB->ParameterCount;
3353 pSMB->MaxReferralLevel = cpu_to_le16(3);
3354 pSMB->hdr.smb_buf_length += byte_count;
3355 pSMB->ByteCount = cpu_to_le16(byte_count);
3357 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3358 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3360 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3361 } else { /* decode response */
3362 /* BB Add logic to parse referrals here */
3363 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3365 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
3366 rc = -EIO; /* bad smb */
3368 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3369 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3372 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
3373 pSMBr->ByteCount, data_offset));
3375 (struct dfs_referral_level_3 *)
3376 (8 /* sizeof start of data block */ +
3378 (char *) &pSMBr->hdr.Protocol);
3379 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",
3380 le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
3381 /* BB This field is actually two bytes in from start of
3382 data block so we could do safety check that DataBlock
3383 begins at address of pSMBr->NumberOfReferrals */
3384 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3386 /* BB Fix below so can return more than one referral */
3387 if(*number_of_UNC_in_array > 1)
3388 *number_of_UNC_in_array = 1;
3390 /* get the length of the strings describing refs */
3392 for(i=0;i<*number_of_UNC_in_array;i++) {
3393 /* make sure that DfsPathOffset not past end */
3394 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3395 if (offset > data_count) {
3396 /* if invalid referral, stop here and do
3397 not try to copy any more */
3398 *number_of_UNC_in_array = i;
3401 temp = ((char *)referrals) + offset;
3403 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3404 name_len += UniStrnlen((wchar_t *)temp,data_count);
3406 name_len += strnlen(temp,data_count);
3409 /* BB add check that referral pointer does not fall off end PDU */
3412 /* BB add check for name_len bigger than bcc */
3414 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3415 if(*targetUNCs == NULL) {
3419 /* copy the ref strings */
3421 (struct dfs_referral_level_3 *)
3422 (8 /* sizeof data hdr */ +
3424 (char *) &pSMBr->hdr.Protocol);
3426 for(i=0;i<*number_of_UNC_in_array;i++) {
3427 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3428 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3429 cifs_strfromUCS_le(*targetUNCs,
3430 (__le16 *) temp, name_len, nls_codepage);
3432 strncpy(*targetUNCs,temp,name_len);
3434 /* BB update target_uncs pointers */
3444 cifs_buf_release(pSMB);
3452 /* Query File System Info such as free space to old servers such as Win 9x */
3454 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3456 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3457 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3458 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3459 FILE_SYSTEM_ALLOC_INFO *response_data;
3461 int bytes_returned = 0;
3462 __u16 params, byte_count;
3464 cFYI(1, ("OldQFSInfo"));
3466 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3470 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3475 params = 2; /* level */
3476 pSMB->TotalDataCount = 0;
3477 pSMB->MaxParameterCount = cpu_to_le16(2);
3478 pSMB->MaxDataCount = cpu_to_le16(1000);
3479 pSMB->MaxSetupCount = 0;
3483 pSMB->Reserved2 = 0;
3484 byte_count = params + 1 /* pad */ ;
3485 pSMB->TotalParameterCount = cpu_to_le16(params);
3486 pSMB->ParameterCount = pSMB->TotalParameterCount;
3487 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3488 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3489 pSMB->DataCount = 0;
3490 pSMB->DataOffset = 0;
3491 pSMB->SetupCount = 1;
3492 pSMB->Reserved3 = 0;
3493 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3494 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3495 pSMB->hdr.smb_buf_length += byte_count;
3496 pSMB->ByteCount = cpu_to_le16(byte_count);
3498 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3499 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3501 cFYI(1, ("Send error in QFSInfo = %d", rc));
3502 } else { /* decode response */
3503 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3505 if (rc || (pSMBr->ByteCount < 18))
3506 rc = -EIO; /* bad smb */
3508 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3509 cFYI(1,("qfsinf resp BCC: %d Offset %d",
3510 pSMBr->ByteCount, data_offset));
3513 (FILE_SYSTEM_ALLOC_INFO *)
3514 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3516 le16_to_cpu(response_data->BytesPerSector) *
3517 le32_to_cpu(response_data->
3518 SectorsPerAllocationUnit);
3520 le32_to_cpu(response_data->TotalAllocationUnits);
3521 FSData->f_bfree = FSData->f_bavail =
3522 le32_to_cpu(response_data->FreeAllocationUnits);
3524 ("Blocks: %lld Free: %lld Block size %ld",
3525 (unsigned long long)FSData->f_blocks,
3526 (unsigned long long)FSData->f_bfree,
3530 cifs_buf_release(pSMB);
3533 goto oldQFSInfoRetry;
3539 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3541 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3542 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3543 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3544 FILE_SYSTEM_INFO *response_data;
3546 int bytes_returned = 0;
3547 __u16 params, byte_count;
3549 cFYI(1, ("In QFSInfo"));
3551 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3556 params = 2; /* level */
3557 pSMB->TotalDataCount = 0;
3558 pSMB->MaxParameterCount = cpu_to_le16(2);
3559 pSMB->MaxDataCount = cpu_to_le16(1000);
3560 pSMB->MaxSetupCount = 0;
3564 pSMB->Reserved2 = 0;
3565 byte_count = params + 1 /* pad */ ;
3566 pSMB->TotalParameterCount = cpu_to_le16(params);
3567 pSMB->ParameterCount = pSMB->TotalParameterCount;
3568 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3569 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3570 pSMB->DataCount = 0;
3571 pSMB->DataOffset = 0;
3572 pSMB->SetupCount = 1;
3573 pSMB->Reserved3 = 0;
3574 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3575 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3576 pSMB->hdr.smb_buf_length += byte_count;
3577 pSMB->ByteCount = cpu_to_le16(byte_count);
3579 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3580 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3582 cFYI(1, ("Send error in QFSInfo = %d", rc));
3583 } else { /* decode response */
3584 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3586 if (rc || (pSMBr->ByteCount < 24))
3587 rc = -EIO; /* bad smb */
3589 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3593 *) (((char *) &pSMBr->hdr.Protocol) +
3596 le32_to_cpu(response_data->BytesPerSector) *
3597 le32_to_cpu(response_data->
3598 SectorsPerAllocationUnit);
3600 le64_to_cpu(response_data->TotalAllocationUnits);
3601 FSData->f_bfree = FSData->f_bavail =
3602 le64_to_cpu(response_data->FreeAllocationUnits);
3604 ("Blocks: %lld Free: %lld Block size %ld",
3605 (unsigned long long)FSData->f_blocks,
3606 (unsigned long long)FSData->f_bfree,
3610 cifs_buf_release(pSMB);
3619 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3621 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3622 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3623 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3624 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3626 int bytes_returned = 0;
3627 __u16 params, byte_count;
3629 cFYI(1, ("In QFSAttributeInfo"));
3631 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3636 params = 2; /* level */
3637 pSMB->TotalDataCount = 0;
3638 pSMB->MaxParameterCount = cpu_to_le16(2);
3639 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3640 pSMB->MaxSetupCount = 0;
3644 pSMB->Reserved2 = 0;
3645 byte_count = params + 1 /* pad */ ;
3646 pSMB->TotalParameterCount = cpu_to_le16(params);
3647 pSMB->ParameterCount = pSMB->TotalParameterCount;
3648 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3649 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3650 pSMB->DataCount = 0;
3651 pSMB->DataOffset = 0;
3652 pSMB->SetupCount = 1;
3653 pSMB->Reserved3 = 0;
3654 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3655 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3656 pSMB->hdr.smb_buf_length += byte_count;
3657 pSMB->ByteCount = cpu_to_le16(byte_count);
3659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3662 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3663 } else { /* decode response */
3664 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3666 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3667 rc = -EIO; /* bad smb */
3669 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3671 (FILE_SYSTEM_ATTRIBUTE_INFO
3672 *) (((char *) &pSMBr->hdr.Protocol) +
3674 memcpy(&tcon->fsAttrInfo, response_data,
3675 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3678 cifs_buf_release(pSMB);
3681 goto QFSAttributeRetry;
3687 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3689 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3690 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3691 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3692 FILE_SYSTEM_DEVICE_INFO *response_data;
3694 int bytes_returned = 0;
3695 __u16 params, byte_count;
3697 cFYI(1, ("In QFSDeviceInfo"));
3699 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3704 params = 2; /* level */
3705 pSMB->TotalDataCount = 0;
3706 pSMB->MaxParameterCount = cpu_to_le16(2);
3707 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3708 pSMB->MaxSetupCount = 0;
3712 pSMB->Reserved2 = 0;
3713 byte_count = params + 1 /* pad */ ;
3714 pSMB->TotalParameterCount = cpu_to_le16(params);
3715 pSMB->ParameterCount = pSMB->TotalParameterCount;
3716 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3717 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3719 pSMB->DataCount = 0;
3720 pSMB->DataOffset = 0;
3721 pSMB->SetupCount = 1;
3722 pSMB->Reserved3 = 0;
3723 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3724 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3725 pSMB->hdr.smb_buf_length += byte_count;
3726 pSMB->ByteCount = cpu_to_le16(byte_count);
3728 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3729 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3731 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3732 } else { /* decode response */
3733 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3735 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3736 rc = -EIO; /* bad smb */
3738 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3740 (FILE_SYSTEM_DEVICE_INFO *)
3741 (((char *) &pSMBr->hdr.Protocol) +
3743 memcpy(&tcon->fsDevInfo, response_data,
3744 sizeof (FILE_SYSTEM_DEVICE_INFO));
3747 cifs_buf_release(pSMB);
3750 goto QFSDeviceRetry;
3756 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3758 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3759 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3760 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3761 FILE_SYSTEM_UNIX_INFO *response_data;
3763 int bytes_returned = 0;
3764 __u16 params, byte_count;
3766 cFYI(1, ("In QFSUnixInfo"));
3768 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3773 params = 2; /* level */
3774 pSMB->TotalDataCount = 0;
3775 pSMB->DataCount = 0;
3776 pSMB->DataOffset = 0;
3777 pSMB->MaxParameterCount = cpu_to_le16(2);
3778 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3779 pSMB->MaxSetupCount = 0;
3783 pSMB->Reserved2 = 0;
3784 byte_count = params + 1 /* pad */ ;
3785 pSMB->ParameterCount = cpu_to_le16(params);
3786 pSMB->TotalParameterCount = pSMB->ParameterCount;
3787 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3788 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3789 pSMB->SetupCount = 1;
3790 pSMB->Reserved3 = 0;
3791 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3792 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3793 pSMB->hdr.smb_buf_length += byte_count;
3794 pSMB->ByteCount = cpu_to_le16(byte_count);
3796 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3797 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3799 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3800 } else { /* decode response */
3801 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3803 if (rc || (pSMBr->ByteCount < 13)) {
3804 rc = -EIO; /* bad smb */
3806 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3808 (FILE_SYSTEM_UNIX_INFO
3809 *) (((char *) &pSMBr->hdr.Protocol) +
3811 memcpy(&tcon->fsUnixInfo, response_data,
3812 sizeof (FILE_SYSTEM_UNIX_INFO));
3815 cifs_buf_release(pSMB);
3825 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3827 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3828 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3829 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3831 int bytes_returned = 0;
3832 __u16 params, param_offset, offset, byte_count;
3834 cFYI(1, ("In SETFSUnixInfo"));
3836 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3841 params = 4; /* 2 bytes zero followed by info level. */
3842 pSMB->MaxSetupCount = 0;
3846 pSMB->Reserved2 = 0;
3847 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3848 offset = param_offset + params;
3850 pSMB->MaxParameterCount = cpu_to_le16(4);
3851 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3852 pSMB->SetupCount = 1;
3853 pSMB->Reserved3 = 0;
3854 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3855 byte_count = 1 /* pad */ + params + 12;
3857 pSMB->DataCount = cpu_to_le16(12);
3858 pSMB->ParameterCount = cpu_to_le16(params);
3859 pSMB->TotalDataCount = pSMB->DataCount;
3860 pSMB->TotalParameterCount = pSMB->ParameterCount;
3861 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3862 pSMB->DataOffset = cpu_to_le16(offset);
3866 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3869 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3870 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3871 pSMB->ClientUnixCap = cpu_to_le64(cap);
3873 pSMB->hdr.smb_buf_length += byte_count;
3874 pSMB->ByteCount = cpu_to_le16(byte_count);
3876 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3877 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3879 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3880 } else { /* decode response */
3881 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3883 rc = -EIO; /* bad smb */
3886 cifs_buf_release(pSMB);
3889 goto SETFSUnixRetry;
3897 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3898 struct kstatfs *FSData)
3900 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3901 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3902 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3903 FILE_SYSTEM_POSIX_INFO *response_data;
3905 int bytes_returned = 0;
3906 __u16 params, byte_count;
3908 cFYI(1, ("In QFSPosixInfo"));
3910 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3915 params = 2; /* level */
3916 pSMB->TotalDataCount = 0;
3917 pSMB->DataCount = 0;
3918 pSMB->DataOffset = 0;
3919 pSMB->MaxParameterCount = cpu_to_le16(2);
3920 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3921 pSMB->MaxSetupCount = 0;
3925 pSMB->Reserved2 = 0;
3926 byte_count = params + 1 /* pad */ ;
3927 pSMB->ParameterCount = cpu_to_le16(params);
3928 pSMB->TotalParameterCount = pSMB->ParameterCount;
3929 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3930 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3931 pSMB->SetupCount = 1;
3932 pSMB->Reserved3 = 0;
3933 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3934 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3935 pSMB->hdr.smb_buf_length += byte_count;
3936 pSMB->ByteCount = cpu_to_le16(byte_count);
3938 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3939 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3941 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3942 } else { /* decode response */
3943 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3945 if (rc || (pSMBr->ByteCount < 13)) {
3946 rc = -EIO; /* bad smb */
3948 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3950 (FILE_SYSTEM_POSIX_INFO
3951 *) (((char *) &pSMBr->hdr.Protocol) +
3954 le32_to_cpu(response_data->BlockSize);
3956 le64_to_cpu(response_data->TotalBlocks);
3958 le64_to_cpu(response_data->BlocksAvail);
3959 if(response_data->UserBlocksAvail == cpu_to_le64(-1)) {
3960 FSData->f_bavail = FSData->f_bfree;
3963 le64_to_cpu(response_data->UserBlocksAvail);
3965 if(response_data->TotalFileNodes != cpu_to_le64(-1))
3967 le64_to_cpu(response_data->TotalFileNodes);
3968 if(response_data->FreeFileNodes != cpu_to_le64(-1))
3970 le64_to_cpu(response_data->FreeFileNodes);
3973 cifs_buf_release(pSMB);
3982 /* We can not use write of zero bytes trick to
3983 set file size due to need for large file support. Also note that
3984 this SetPathInfo is preferred to SetFileInfo based method in next
3985 routine which is only needed to work around a sharing violation bug
3986 in Samba which this routine can run into */
3989 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3990 __u64 size, int SetAllocation,
3991 const struct nls_table *nls_codepage, int remap)
3993 struct smb_com_transaction2_spi_req *pSMB = NULL;
3994 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3995 struct file_end_of_file_info *parm_data;
3998 int bytes_returned = 0;
3999 __u16 params, byte_count, data_count, param_offset, offset;
4001 cFYI(1, ("In SetEOF"));
4003 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4008 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4010 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4011 PATH_MAX, nls_codepage, remap);
4012 name_len++; /* trailing null */
4014 } else { /* BB improve the check for buffer overruns BB */
4015 name_len = strnlen(fileName, PATH_MAX);
4016 name_len++; /* trailing null */
4017 strncpy(pSMB->FileName, fileName, name_len);
4019 params = 6 + name_len;
4020 data_count = sizeof (struct file_end_of_file_info);
4021 pSMB->MaxParameterCount = cpu_to_le16(2);
4022 pSMB->MaxDataCount = cpu_to_le16(4100);
4023 pSMB->MaxSetupCount = 0;
4027 pSMB->Reserved2 = 0;
4028 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4029 InformationLevel) - 4;
4030 offset = param_offset + params;
4032 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4033 pSMB->InformationLevel =
4034 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4036 pSMB->InformationLevel =
4037 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4038 } else /* Set File Size */ {
4039 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4040 pSMB->InformationLevel =
4041 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4043 pSMB->InformationLevel =
4044 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4048 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4050 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4051 pSMB->DataOffset = cpu_to_le16(offset);
4052 pSMB->SetupCount = 1;
4053 pSMB->Reserved3 = 0;
4054 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4055 byte_count = 3 /* pad */ + params + data_count;
4056 pSMB->DataCount = cpu_to_le16(data_count);
4057 pSMB->TotalDataCount = pSMB->DataCount;
4058 pSMB->ParameterCount = cpu_to_le16(params);
4059 pSMB->TotalParameterCount = pSMB->ParameterCount;
4060 pSMB->Reserved4 = 0;
4061 pSMB->hdr.smb_buf_length += byte_count;
4062 parm_data->FileSize = cpu_to_le64(size);
4063 pSMB->ByteCount = cpu_to_le16(byte_count);
4064 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4065 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4067 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4070 cifs_buf_release(pSMB);
4079 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4080 __u16 fid, __u32 pid_of_opener, int SetAllocation)
4082 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4083 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4085 struct file_end_of_file_info *parm_data;
4087 int bytes_returned = 0;
4088 __u16 params, param_offset, offset, byte_count, count;
4090 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4092 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4097 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4099 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4100 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4103 pSMB->MaxSetupCount = 0;
4107 pSMB->Reserved2 = 0;
4108 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4109 offset = param_offset + params;
4111 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4113 count = sizeof(struct file_end_of_file_info);
4114 pSMB->MaxParameterCount = cpu_to_le16(2);
4115 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4116 pSMB->SetupCount = 1;
4117 pSMB->Reserved3 = 0;
4118 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4119 byte_count = 3 /* pad */ + params + count;
4120 pSMB->DataCount = cpu_to_le16(count);
4121 pSMB->ParameterCount = cpu_to_le16(params);
4122 pSMB->TotalDataCount = pSMB->DataCount;
4123 pSMB->TotalParameterCount = pSMB->ParameterCount;
4124 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4126 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4128 pSMB->DataOffset = cpu_to_le16(offset);
4129 parm_data->FileSize = cpu_to_le64(size);
4132 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4133 pSMB->InformationLevel =
4134 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4136 pSMB->InformationLevel =
4137 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4138 } else /* Set File Size */ {
4139 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4140 pSMB->InformationLevel =
4141 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4143 pSMB->InformationLevel =
4144 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4146 pSMB->Reserved4 = 0;
4147 pSMB->hdr.smb_buf_length += byte_count;
4148 pSMB->ByteCount = cpu_to_le16(byte_count);
4149 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4150 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4153 ("Send error in SetFileInfo (SetFileSize) = %d",
4158 cifs_small_buf_release(pSMB);
4160 /* Note: On -EAGAIN error only caller can retry on handle based calls
4161 since file handle passed in no longer valid */
4166 /* Some legacy servers such as NT4 require that the file times be set on
4167 an open handle, rather than by pathname - this is awkward due to
4168 potential access conflicts on the open, but it is unavoidable for these
4169 old servers since the only other choice is to go from 100 nanosecond DCE
4170 time and resort to the original setpathinfo level which takes the ancient
4171 DOS time format with 2 second granularity */
4173 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
4176 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4177 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
4180 int bytes_returned = 0;
4181 __u16 params, param_offset, offset, byte_count, count;
4183 cFYI(1, ("Set Times (via SetFileInfo)"));
4184 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4189 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
4191 /* At this point there is no need to override the current pid
4192 with the pid of the opener, but that could change if we someday
4193 use an existing handle (rather than opening one on the fly) */
4194 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4195 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
4198 pSMB->MaxSetupCount = 0;
4202 pSMB->Reserved2 = 0;
4203 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4204 offset = param_offset + params;
4206 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4208 count = sizeof (FILE_BASIC_INFO);
4209 pSMB->MaxParameterCount = cpu_to_le16(2);
4210 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4211 pSMB->SetupCount = 1;
4212 pSMB->Reserved3 = 0;
4213 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4214 byte_count = 3 /* pad */ + params + count;
4215 pSMB->DataCount = cpu_to_le16(count);
4216 pSMB->ParameterCount = cpu_to_le16(params);
4217 pSMB->TotalDataCount = pSMB->DataCount;
4218 pSMB->TotalParameterCount = pSMB->ParameterCount;
4219 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4220 pSMB->DataOffset = cpu_to_le16(offset);
4222 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4223 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4225 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4226 pSMB->Reserved4 = 0;
4227 pSMB->hdr.smb_buf_length += byte_count;
4228 pSMB->ByteCount = cpu_to_le16(byte_count);
4229 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
4230 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4231 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4233 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4236 cifs_small_buf_release(pSMB);
4238 /* Note: On -EAGAIN error only caller can retry on handle based calls
4239 since file handle passed in no longer valid */
4246 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4247 const FILE_BASIC_INFO * data,
4248 const struct nls_table *nls_codepage, int remap)
4250 TRANSACTION2_SPI_REQ *pSMB = NULL;
4251 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4254 int bytes_returned = 0;
4256 __u16 params, param_offset, offset, byte_count, count;
4258 cFYI(1, ("In SetTimes"));
4261 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4266 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4268 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4269 PATH_MAX, nls_codepage, remap);
4270 name_len++; /* trailing null */
4272 } else { /* BB improve the check for buffer overruns BB */
4273 name_len = strnlen(fileName, PATH_MAX);
4274 name_len++; /* trailing null */
4275 strncpy(pSMB->FileName, fileName, name_len);
4278 params = 6 + name_len;
4279 count = sizeof (FILE_BASIC_INFO);
4280 pSMB->MaxParameterCount = cpu_to_le16(2);
4281 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4282 pSMB->MaxSetupCount = 0;
4286 pSMB->Reserved2 = 0;
4287 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4288 InformationLevel) - 4;
4289 offset = param_offset + params;
4290 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4291 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4292 pSMB->DataOffset = cpu_to_le16(offset);
4293 pSMB->SetupCount = 1;
4294 pSMB->Reserved3 = 0;
4295 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4296 byte_count = 3 /* pad */ + params + count;
4298 pSMB->DataCount = cpu_to_le16(count);
4299 pSMB->ParameterCount = cpu_to_le16(params);
4300 pSMB->TotalDataCount = pSMB->DataCount;
4301 pSMB->TotalParameterCount = pSMB->ParameterCount;
4302 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4303 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4305 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4306 pSMB->Reserved4 = 0;
4307 pSMB->hdr.smb_buf_length += byte_count;
4308 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4309 pSMB->ByteCount = cpu_to_le16(byte_count);
4310 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4311 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4313 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4316 cifs_buf_release(pSMB);
4324 /* Can not be used to set time stamps yet (due to old DOS time format) */
4325 /* Can be used to set attributes */
4326 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
4327 handling it anyway and NT4 was what we thought it would be needed for
4328 Do not delete it until we prove whether needed for Win9x though */
4330 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4331 __u16 dos_attrs, const struct nls_table *nls_codepage)
4333 SETATTR_REQ *pSMB = NULL;
4334 SETATTR_RSP *pSMBr = NULL;
4339 cFYI(1, ("In SetAttrLegacy"));
4342 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4349 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
4350 PATH_MAX, nls_codepage);
4351 name_len++; /* trailing null */
4353 } else { /* BB improve the check for buffer overruns BB */
4354 name_len = strnlen(fileName, PATH_MAX);
4355 name_len++; /* trailing null */
4356 strncpy(pSMB->fileName, fileName, name_len);
4358 pSMB->attr = cpu_to_le16(dos_attrs);
4359 pSMB->BufferFormat = 0x04;
4360 pSMB->hdr.smb_buf_length += name_len + 1;
4361 pSMB->ByteCount = cpu_to_le16(name_len + 1);
4362 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4363 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4365 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4368 cifs_buf_release(pSMB);
4371 goto SetAttrLgcyRetry;
4375 #endif /* temporarily unneeded SetAttr legacy function */
4378 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4379 char *fileName, __u64 mode, __u64 uid, __u64 gid,
4380 dev_t device, const struct nls_table *nls_codepage,
4383 TRANSACTION2_SPI_REQ *pSMB = NULL;
4384 TRANSACTION2_SPI_RSP *pSMBr = NULL;
4387 int bytes_returned = 0;
4388 FILE_UNIX_BASIC_INFO *data_offset;
4389 __u16 params, param_offset, offset, count, byte_count;
4391 cFYI(1, ("In SetUID/GID/Mode"));
4393 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4398 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4400 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4401 PATH_MAX, nls_codepage, remap);
4402 name_len++; /* trailing null */
4404 } else { /* BB improve the check for buffer overruns BB */
4405 name_len = strnlen(fileName, PATH_MAX);
4406 name_len++; /* trailing null */
4407 strncpy(pSMB->FileName, fileName, name_len);
4410 params = 6 + name_len;
4411 count = sizeof (FILE_UNIX_BASIC_INFO);
4412 pSMB->MaxParameterCount = cpu_to_le16(2);
4413 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4414 pSMB->MaxSetupCount = 0;
4418 pSMB->Reserved2 = 0;
4419 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4420 InformationLevel) - 4;
4421 offset = param_offset + params;
4423 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4425 memset(data_offset, 0, count);
4426 pSMB->DataOffset = cpu_to_le16(offset);
4427 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4428 pSMB->SetupCount = 1;
4429 pSMB->Reserved3 = 0;
4430 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4431 byte_count = 3 /* pad */ + params + count;
4432 pSMB->ParameterCount = cpu_to_le16(params);
4433 pSMB->DataCount = cpu_to_le16(count);
4434 pSMB->TotalParameterCount = pSMB->ParameterCount;
4435 pSMB->TotalDataCount = pSMB->DataCount;
4436 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4437 pSMB->Reserved4 = 0;
4438 pSMB->hdr.smb_buf_length += byte_count;
4439 data_offset->Uid = cpu_to_le64(uid);
4440 data_offset->Gid = cpu_to_le64(gid);
4441 /* better to leave device as zero when it is */
4442 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4443 data_offset->DevMinor = cpu_to_le64(MINOR(device));
4444 data_offset->Permissions = cpu_to_le64(mode);
4447 data_offset->Type = cpu_to_le32(UNIX_FILE);
4448 else if(S_ISDIR(mode))
4449 data_offset->Type = cpu_to_le32(UNIX_DIR);
4450 else if(S_ISLNK(mode))
4451 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4452 else if(S_ISCHR(mode))
4453 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4454 else if(S_ISBLK(mode))
4455 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4456 else if(S_ISFIFO(mode))
4457 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4458 else if(S_ISSOCK(mode))
4459 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4462 pSMB->ByteCount = cpu_to_le16(byte_count);
4463 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4464 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4466 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4470 cifs_buf_release(pSMB);
4476 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
4477 const int notify_subdirs, const __u16 netfid,
4478 __u32 filter, struct file * pfile, int multishot,
4479 const struct nls_table *nls_codepage)
4482 struct smb_com_transaction_change_notify_req * pSMB = NULL;
4483 struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
4484 struct dir_notify_req *dnotify_req;
4487 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4488 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4493 pSMB->TotalParameterCount = 0 ;
4494 pSMB->TotalDataCount = 0;
4495 pSMB->MaxParameterCount = cpu_to_le32(2);
4496 /* BB find exact data count max from sess structure BB */
4497 pSMB->MaxDataCount = 0; /* same in little endian or be */
4498 /* BB VERIFY verify which is correct for above BB */
4499 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
4500 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
4502 pSMB->MaxSetupCount = 4;
4504 pSMB->ParameterOffset = 0;
4505 pSMB->DataCount = 0;
4506 pSMB->DataOffset = 0;
4507 pSMB->SetupCount = 4; /* single byte does not need le conversion */
4508 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4509 pSMB->ParameterCount = pSMB->TotalParameterCount;
4511 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4512 pSMB->Reserved2 = 0;
4513 pSMB->CompletionFilter = cpu_to_le32(filter);
4514 pSMB->Fid = netfid; /* file handle always le */
4515 pSMB->ByteCount = 0;
4517 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4518 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4520 cFYI(1, ("Error in Notify = %d", rc));
4522 /* Add file to outstanding requests */
4523 /* BB change to kmem cache alloc */
4524 dnotify_req = (struct dir_notify_req *) kmalloc(
4525 sizeof(struct dir_notify_req),
4528 dnotify_req->Pid = pSMB->hdr.Pid;
4529 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4530 dnotify_req->Mid = pSMB->hdr.Mid;
4531 dnotify_req->Tid = pSMB->hdr.Tid;
4532 dnotify_req->Uid = pSMB->hdr.Uid;
4533 dnotify_req->netfid = netfid;
4534 dnotify_req->pfile = pfile;
4535 dnotify_req->filter = filter;
4536 dnotify_req->multishot = multishot;
4537 spin_lock(&GlobalMid_Lock);
4538 list_add_tail(&dnotify_req->lhead,
4539 &GlobalDnotifyReqList);
4540 spin_unlock(&GlobalMid_Lock);
4544 cifs_buf_release(pSMB);
4547 #ifdef CONFIG_CIFS_XATTR
4549 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4550 const unsigned char *searchName,
4551 char * EAData, size_t buf_size,
4552 const struct nls_table *nls_codepage, int remap)
4554 /* BB assumes one setup word */
4555 TRANSACTION2_QPI_REQ *pSMB = NULL;
4556 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4560 struct fea * temp_fea;
4562 __u16 params, byte_count;
4564 cFYI(1, ("In Query All EAs path %s", searchName));
4566 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4571 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4573 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4574 PATH_MAX, nls_codepage, remap);
4575 name_len++; /* trailing null */
4577 } else { /* BB improve the check for buffer overruns BB */
4578 name_len = strnlen(searchName, PATH_MAX);
4579 name_len++; /* trailing null */
4580 strncpy(pSMB->FileName, searchName, name_len);
4583 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4584 pSMB->TotalDataCount = 0;
4585 pSMB->MaxParameterCount = cpu_to_le16(2);
4586 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4587 pSMB->MaxSetupCount = 0;
4591 pSMB->Reserved2 = 0;
4592 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4593 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4594 pSMB->DataCount = 0;
4595 pSMB->DataOffset = 0;
4596 pSMB->SetupCount = 1;
4597 pSMB->Reserved3 = 0;
4598 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4599 byte_count = params + 1 /* pad */ ;
4600 pSMB->TotalParameterCount = cpu_to_le16(params);
4601 pSMB->ParameterCount = pSMB->TotalParameterCount;
4602 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4603 pSMB->Reserved4 = 0;
4604 pSMB->hdr.smb_buf_length += byte_count;
4605 pSMB->ByteCount = cpu_to_le16(byte_count);
4607 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4608 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4610 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4611 } else { /* decode response */
4612 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4614 /* BB also check enough total bytes returned */
4615 /* BB we need to improve the validity checking
4616 of these trans2 responses */
4617 if (rc || (pSMBr->ByteCount < 4))
4618 rc = -EIO; /* bad smb */
4619 /* else if (pFindData){
4620 memcpy((char *) pFindData,
4621 (char *) &pSMBr->hdr.Protocol +
4624 /* check that length of list is not more than bcc */
4625 /* check that each entry does not go beyond length
4627 /* check that each element of each entry does not
4628 go beyond end of list */
4629 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4630 struct fealist * ea_response_data;
4632 /* validate_trans2_offsets() */
4633 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4634 ea_response_data = (struct fealist *)
4635 (((char *) &pSMBr->hdr.Protocol) +
4637 name_len = le32_to_cpu(ea_response_data->list_len);
4638 cFYI(1,("ea length %d", name_len));
4640 /* returned EA size zeroed at top of function */
4641 cFYI(1,("empty EA list returned from server"));
4643 /* account for ea list len */
4645 temp_fea = ea_response_data->list;
4646 temp_ptr = (char *)temp_fea;
4647 while(name_len > 0) {
4651 rc += temp_fea->name_len;
4652 /* account for prefix user. and trailing null */
4654 if(rc<(int)buf_size) {
4655 memcpy(EAData,"user.",5);
4657 memcpy(EAData,temp_ptr,temp_fea->name_len);
4658 EAData+=temp_fea->name_len;
4659 /* null terminate name */
4661 EAData = EAData + 1;
4662 } else if(buf_size == 0) {
4663 /* skip copy - calc size only */
4665 /* stop before overrun buffer */
4669 name_len -= temp_fea->name_len;
4670 temp_ptr += temp_fea->name_len;
4671 /* account for trailing null */
4674 value_len = le16_to_cpu(temp_fea->value_len);
4675 name_len -= value_len;
4676 temp_ptr += value_len;
4677 /* BB check that temp_ptr is still within smb BB*/
4678 /* no trailing null to account for in value len */
4679 /* go on to next EA */
4680 temp_fea = (struct fea *)temp_ptr;
4686 cifs_buf_release(pSMB);
4693 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4694 const unsigned char * searchName,const unsigned char * ea_name,
4695 unsigned char * ea_value, size_t buf_size,
4696 const struct nls_table *nls_codepage, int remap)
4698 TRANSACTION2_QPI_REQ *pSMB = NULL;
4699 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4703 struct fea * temp_fea;
4705 __u16 params, byte_count;
4707 cFYI(1, ("In Query EA path %s", searchName));
4709 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4714 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4716 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4717 PATH_MAX, nls_codepage, remap);
4718 name_len++; /* trailing null */
4720 } else { /* BB improve the check for buffer overruns BB */
4721 name_len = strnlen(searchName, PATH_MAX);
4722 name_len++; /* trailing null */
4723 strncpy(pSMB->FileName, searchName, name_len);
4726 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4727 pSMB->TotalDataCount = 0;
4728 pSMB->MaxParameterCount = cpu_to_le16(2);
4729 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4730 pSMB->MaxSetupCount = 0;
4734 pSMB->Reserved2 = 0;
4735 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4736 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4737 pSMB->DataCount = 0;
4738 pSMB->DataOffset = 0;
4739 pSMB->SetupCount = 1;
4740 pSMB->Reserved3 = 0;
4741 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4742 byte_count = params + 1 /* pad */ ;
4743 pSMB->TotalParameterCount = cpu_to_le16(params);
4744 pSMB->ParameterCount = pSMB->TotalParameterCount;
4745 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4746 pSMB->Reserved4 = 0;
4747 pSMB->hdr.smb_buf_length += byte_count;
4748 pSMB->ByteCount = cpu_to_le16(byte_count);
4750 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4751 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4753 cFYI(1, ("Send error in Query EA = %d", rc));
4754 } else { /* decode response */
4755 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4757 /* BB also check enough total bytes returned */
4758 /* BB we need to improve the validity checking
4759 of these trans2 responses */
4760 if (rc || (pSMBr->ByteCount < 4))
4761 rc = -EIO; /* bad smb */
4762 /* else if (pFindData){
4763 memcpy((char *) pFindData,
4764 (char *) &pSMBr->hdr.Protocol +
4767 /* check that length of list is not more than bcc */
4768 /* check that each entry does not go beyond length
4770 /* check that each element of each entry does not
4771 go beyond end of list */
4772 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4773 struct fealist * ea_response_data;
4775 /* validate_trans2_offsets() */
4776 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4777 ea_response_data = (struct fealist *)
4778 (((char *) &pSMBr->hdr.Protocol) +
4780 name_len = le32_to_cpu(ea_response_data->list_len);
4781 cFYI(1,("ea length %d", name_len));
4783 /* returned EA size zeroed at top of function */
4784 cFYI(1,("empty EA list returned from server"));
4786 /* account for ea list len */
4788 temp_fea = ea_response_data->list;
4789 temp_ptr = (char *)temp_fea;
4790 /* loop through checking if we have a matching
4791 name and then return the associated value */
4792 while(name_len > 0) {
4796 value_len = le16_to_cpu(temp_fea->value_len);
4797 /* BB validate that value_len falls within SMB,
4798 even though maximum for name_len is 255 */
4799 if(memcmp(temp_fea->name,ea_name,
4800 temp_fea->name_len) == 0) {
4803 /* account for prefix user. and trailing null */
4804 if(rc<=(int)buf_size) {
4806 temp_fea->name+temp_fea->name_len+1,
4808 /* ea values, unlike ea names,
4809 are not null terminated */
4810 } else if(buf_size == 0) {
4811 /* skip copy - calc size only */
4813 /* stop before overrun buffer */
4818 name_len -= temp_fea->name_len;
4819 temp_ptr += temp_fea->name_len;
4820 /* account for trailing null */
4823 name_len -= value_len;
4824 temp_ptr += value_len;
4825 /* no trailing null to account for in value len */
4826 /* go on to next EA */
4827 temp_fea = (struct fea *)temp_ptr;
4833 cifs_buf_release(pSMB);
4841 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4842 const char * ea_name, const void * ea_value,
4843 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4846 struct smb_com_transaction2_spi_req *pSMB = NULL;
4847 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4848 struct fealist *parm_data;
4851 int bytes_returned = 0;
4852 __u16 params, param_offset, byte_count, offset, count;
4854 cFYI(1, ("In SetEA"));
4856 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4861 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4863 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4864 PATH_MAX, nls_codepage, remap);
4865 name_len++; /* trailing null */
4867 } else { /* BB improve the check for buffer overruns BB */
4868 name_len = strnlen(fileName, PATH_MAX);
4869 name_len++; /* trailing null */
4870 strncpy(pSMB->FileName, fileName, name_len);
4873 params = 6 + name_len;
4875 /* done calculating parms using name_len of file name,
4876 now use name_len to calculate length of ea name
4877 we are going to create in the inode xattrs */
4881 name_len = strnlen(ea_name,255);
4883 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4884 pSMB->MaxParameterCount = cpu_to_le16(2);
4885 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4886 pSMB->MaxSetupCount = 0;
4890 pSMB->Reserved2 = 0;
4891 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4892 InformationLevel) - 4;
4893 offset = param_offset + params;
4894 pSMB->InformationLevel =
4895 cpu_to_le16(SMB_SET_FILE_EA);
4898 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4900 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4901 pSMB->DataOffset = cpu_to_le16(offset);
4902 pSMB->SetupCount = 1;
4903 pSMB->Reserved3 = 0;
4904 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4905 byte_count = 3 /* pad */ + params + count;
4906 pSMB->DataCount = cpu_to_le16(count);
4907 parm_data->list_len = cpu_to_le32(count);
4908 parm_data->list[0].EA_flags = 0;
4909 /* we checked above that name len is less than 255 */
4910 parm_data->list[0].name_len = (__u8)name_len;;
4911 /* EA names are always ASCII */
4913 strncpy(parm_data->list[0].name,ea_name,name_len);
4914 parm_data->list[0].name[name_len] = 0;
4915 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4916 /* caller ensures that ea_value_len is less than 64K but
4917 we need to ensure that it fits within the smb */
4919 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4920 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4922 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4924 pSMB->TotalDataCount = pSMB->DataCount;
4925 pSMB->ParameterCount = cpu_to_le16(params);
4926 pSMB->TotalParameterCount = pSMB->ParameterCount;
4927 pSMB->Reserved4 = 0;
4928 pSMB->hdr.smb_buf_length += byte_count;
4929 pSMB->ByteCount = cpu_to_le16(byte_count);
4930 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4931 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4933 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4936 cifs_buf_release(pSMB);