vserver 1.9.3
[linux-2.6.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2003
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
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.
13  *
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.
18  *
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
22  */
23
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 */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <asm/uaccess.h>
34 #include "cifspdu.h"
35 #include "cifsglob.h"
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39
40 #ifdef CONFIG_CIFS_POSIX
41 static struct {
42         int index;
43         char *name;
44 } protocols[] = {
45         {CIFS_PROT, "\2NT LM 0.12"}, 
46         {CIFS_PROT, "\2POSIX 2"},
47         {BAD_PROT, "\2"}
48 };
49 #else
50 static struct {
51         int index;
52         char *name;
53 } protocols[] = {
54         {CIFS_PROT, "\2NT LM 0.12"}, 
55         {BAD_PROT, "\2"}
56 };
57 #endif
58
59
60 /* Mark as invalid, all open files on tree connections since they
61    were closed when session to server was lost */
62 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
63 {
64         struct cifsFileInfo *open_file = NULL;
65         struct list_head * tmp;
66         struct list_head * tmp1;
67
68 /* list all files open on tree connection and mark them invalid */
69         write_lock(&GlobalSMBSeslock);
70         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
71                 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
72                 if(open_file) {
73                         open_file->invalidHandle = TRUE;
74                 }
75         }
76         write_unlock(&GlobalSMBSeslock);
77         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
78 }
79
80 static int
81 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
82          void **request_buf /* returned */ ,
83          void **response_buf /* returned */ )
84 {
85         int rc = 0;
86
87         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
88            check for tcp and smb session status done differently
89            for those three - in the calling routine */
90         if(tcon) {
91                 if((tcon->ses) && (tcon->ses->server)){
92                         struct nls_table *nls_codepage;
93                                 /* Give Demultiplex thread up to 10 seconds to 
94                                         reconnect, should be greater than cifs socket
95                                         timeout which is 7 seconds */
96                         while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
97                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
98                                         (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
99                                 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100                                         /* on "soft" mounts we wait once */
101                                         if((tcon->retry == FALSE) || 
102                                            (tcon->ses->status == CifsExiting)) {
103                                                 cFYI(1,("gave up waiting on reconnect in smb_init"));
104                                                 return -EHOSTDOWN;
105                                         } /* else "hard" mount - keep retrying until 
106                                         process is killed or server comes back up */
107                                 } else /* TCP session is reestablished now */
108                                         break;
109                                  
110                         }
111                         
112                         nls_codepage = load_nls_default();
113                 /* need to prevent multiple threads trying to
114                 simultaneously reconnect the same SMB session */
115                         down(&tcon->ses->sesSem);
116                         if(tcon->ses->status == CifsNeedReconnect)
117                                 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
118                         if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
119                                 mark_open_files_invalid(tcon);
120                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
121                                         nls_codepage);
122                                 up(&tcon->ses->sesSem);
123                                 if(rc == 0)
124                                         atomic_inc(&tconInfoReconnectCount);
125
126                                 cFYI(1, ("reconnect tcon rc = %d", rc));
127                                 /* Removed call to reopen open files here - 
128                                         it is safer (and faster) to reopen files
129                                         one at a time as needed in read and write */
130
131                                 /* Check if handle based operation so we 
132                                         know whether we can continue or not without
133                                         returning to caller to reset file handle */
134                                 switch(smb_command) {
135                                         case SMB_COM_READ_ANDX:
136                                         case SMB_COM_WRITE_ANDX:
137                                         case SMB_COM_CLOSE:
138                                         case SMB_COM_FIND_CLOSE2:
139                                         case SMB_COM_LOCKING_ANDX: {
140                                                 unload_nls(nls_codepage);
141                                                 return -EAGAIN;
142                                         }
143                                 }
144                         } else {
145                                 up(&tcon->ses->sesSem);
146                         }
147                         unload_nls(nls_codepage);
148
149                 } else {
150                         return -EIO;
151                 }
152         }
153         if(rc)
154                 return rc;
155
156         *request_buf = cifs_buf_get();
157         if (*request_buf == 0) {
158                 /* BB should we add a retry in here if not a writepage? */
159                 return -ENOMEM;
160         }
161     /* Although the original thought was we needed the response buf for  */
162     /* potential retries of smb operations it turns out we can determine */
163     /* from the mid flags when the request buffer can be resent without  */
164     /* having to use a second distinct buffer for the response */
165         *response_buf = *request_buf; 
166
167         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
168                         wct /*wct */ );
169
170 #ifdef CONFIG_CIFS_STATS
171         if(tcon != NULL) {
172                 atomic_inc(&tcon->num_smbs_sent);
173         }
174 #endif
175         return rc;
176 }
177
178 int
179 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
180 {
181         NEGOTIATE_REQ *pSMB;
182         NEGOTIATE_RSP *pSMBr;
183         int rc = 0;
184         int bytes_returned;
185         struct TCP_Server_Info * server;
186         u16 count;
187
188         if(ses->server)
189                 server = ses->server;
190         else {
191                 rc = -EIO;
192                 return rc;
193         }
194         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
195                       (void **) &pSMB, (void **) &pSMBr);
196         if (rc)
197                 return rc;
198
199         pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
200         if (extended_security)
201                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
202
203         count = strlen(protocols[0].name) + 1;
204         strncpy(pSMB->DialectsArray, protocols[0].name, 30);    
205     /* null guaranteed to be at end of source and target buffers anyway */
206
207         pSMB->hdr.smb_buf_length += count;
208         pSMB->ByteCount = cpu_to_le16(count);
209
210         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
211                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
212         if (rc == 0) {
213                 server->secMode = pSMBr->SecurityMode;  
214                 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
215                 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
216                 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
217                 /* probably no need to store and check maxvcs */
218                 server->maxBuf =
219                         min(le32_to_cpu(pSMBr->MaxBufferSize),
220                         (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
221                 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
222                 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
223                 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
224                 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
225                 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);  
226         /* BB with UTC do we ever need to be using srvr timezone? */
227                 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
228                         memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
229                                CIFS_CRYPTO_KEY_SIZE);
230                 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
231                            && (pSMBr->EncryptionKeyLength == 0)) {
232                         /* decode security blob */
233                 } else
234                         rc = -EIO;
235
236                 /* BB might be helpful to save off the domain of server here */
237
238                 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
239                         (server->capabilities & CAP_EXTENDED_SECURITY)) {
240                         count = pSMBr->ByteCount;
241                         if (count < 16)
242                                 rc = -EIO;
243                         else if (count == 16) {
244                                 server->secType = RawNTLMSSP;
245                                 if (server->socketUseCount.counter > 1) {
246                                         if (memcmp
247                                                 (server->server_GUID,
248                                                 pSMBr->u.extended_response.
249                                                 GUID, 16) != 0) {
250                                                 cFYI(1,
251                                                         ("UID of server does not match previous connection to same ip address"));
252                                                 memcpy(server->
253                                                         server_GUID,
254                                                         pSMBr->u.
255                                                         extended_response.
256                                                         GUID, 16);
257                                         }
258                                 } else
259                                         memcpy(server->server_GUID,
260                                                pSMBr->u.extended_response.
261                                                GUID, 16);
262                         } else {
263                                 rc = decode_negTokenInit(pSMBr->u.
264                                                          extended_response.
265                                                          SecurityBlob,
266                                                          count - 16,
267                                                          &server->secType);
268                         }
269                 } else
270                         server->capabilities &= ~CAP_EXTENDED_SECURITY;
271                 if(sign_CIFS_PDUs == FALSE) {        
272                         if(server->secMode & SECMODE_SIGN_REQUIRED)
273                                 cERROR(1,
274                                  ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
275                         server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
276                 } else if(sign_CIFS_PDUs == 1) {
277                         if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
278                                 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
279                 }
280                                 
281         }
282         if (pSMB)
283                 cifs_buf_release(pSMB);
284         return rc;
285 }
286
287 int
288 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
289 {
290         struct smb_hdr *smb_buffer;
291         struct smb_hdr *smb_buffer_response;
292         int rc = 0;
293         int length;
294
295         cFYI(1, ("In tree disconnect"));
296         /*
297          *  If last user of the connection and
298          *  connection alive - disconnect it
299          *  If this is the last connection on the server session disconnect it
300          *  (and inside session disconnect we should check if tcp socket needs 
301          *  to be freed and kernel thread woken up).
302          */
303         if (tcon)
304                 down(&tcon->tconSem);
305         else
306                 return -EIO;
307
308         atomic_dec(&tcon->useCount);
309         if (atomic_read(&tcon->useCount) > 0) {
310                 up(&tcon->tconSem);
311                 return -EBUSY;
312         }
313
314         /* No need to return error on this operation if tid invalidated and 
315         closed on server already e.g. due to tcp session crashing */
316         if(tcon->tidStatus == CifsNeedReconnect) {
317                 up(&tcon->tconSem);
318                 return 0;  
319         }
320
321         if((tcon->ses == 0) || (tcon->ses->server == 0)) {    
322                 up(&tcon->tconSem);
323                 return -EIO;
324         }
325
326         rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
327                       (void **) &smb_buffer, (void **) &smb_buffer_response);
328         if (rc) {
329                 up(&tcon->tconSem);
330                 return rc;
331         }
332         rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
333                          &length, 0);
334         if (rc)
335                 cFYI(1, (" Tree disconnect failed %d", rc));
336
337         if (smb_buffer)
338                 cifs_buf_release(smb_buffer);
339         up(&tcon->tconSem);
340
341         /* No need to return error on this operation if tid invalidated and 
342         closed on server already e.g. due to tcp session crashing */
343         if (rc == -EAGAIN)
344                 rc = 0;
345
346         return rc;
347 }
348
349 int
350 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
351 {
352         struct smb_hdr *smb_buffer_response;
353         LOGOFF_ANDX_REQ *pSMB;
354         int rc = 0;
355         int length;
356
357         cFYI(1, ("In SMBLogoff for session disconnect"));
358         if (ses)
359                 down(&ses->sesSem);
360         else
361                 return -EIO;
362
363         atomic_dec(&ses->inUse);
364         if (atomic_read(&ses->inUse) > 0) {
365                 up(&ses->sesSem);
366                 return -EBUSY;
367         }
368
369         rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
370                  (void **) &pSMB, (void **) &smb_buffer_response);
371         
372         if(ses->server) {
373                 if(ses->server->secMode & 
374                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
375                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
376         }
377
378         if (rc) {
379                 up(&ses->sesSem);
380                 return rc;
381         }
382
383         pSMB->hdr.Uid = ses->Suid;
384
385         pSMB->AndXCommand = 0xFF;
386         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
387                          smb_buffer_response, &length, 0);
388         if (ses->server) {
389                 atomic_dec(&ses->server->socketUseCount);
390                 if (atomic_read(&ses->server->socketUseCount) == 0) {
391                         spin_lock(&GlobalMid_Lock);
392                         ses->server->tcpStatus = CifsExiting;
393                         spin_unlock(&GlobalMid_Lock);
394                         rc = -ESHUTDOWN;
395                 }
396         }
397         if (pSMB)
398                 cifs_buf_release(pSMB);
399         up(&ses->sesSem);
400
401         /* if session dead then we do not need to do ulogoff,
402                 since server closed smb session, no sense reporting 
403                 error */
404         if (rc == -EAGAIN)
405                 rc = 0;
406         return rc;
407 }
408
409 int
410 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
411                const char *fileName, const struct nls_table *nls_codepage)
412 {
413         DELETE_FILE_REQ *pSMB = NULL;
414         DELETE_FILE_RSP *pSMBr = NULL;
415         int rc = 0;
416         int bytes_returned;
417         int name_len;
418
419 DelFileRetry:
420         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
421                       (void **) &pSMBr);
422         if (rc)
423                 return rc;
424
425         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
426                 name_len =
427                     cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
428                                   /* find define for this maxpathcomponent */
429                                   , nls_codepage);
430                 name_len++;     /* trailing null */
431                 name_len *= 2;
432         } else {                /* BB improve the check for buffer overruns BB */
433                 name_len = strnlen(fileName, 530);
434                 name_len++;     /* trailing null */
435                 strncpy(pSMB->fileName, fileName, name_len);
436         }
437         pSMB->SearchAttributes =
438             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
439         pSMB->BufferFormat = 0x04;
440         pSMB->hdr.smb_buf_length += name_len + 1;
441         pSMB->ByteCount = cpu_to_le16(name_len + 1);
442         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
443                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
444         if (rc) {
445                 cFYI(1, ("Error in RMFile = %d", rc));
446         } 
447 #ifdef CONFIG_CIFS_STATS
448         else {
449                 atomic_inc(&tcon->num_deletes);
450         }
451 #endif
452
453         if (pSMB)
454                 cifs_buf_release(pSMB);
455         if (rc == -EAGAIN)
456                 goto DelFileRetry;
457
458         return rc;
459 }
460
461 int
462 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
463              const char *dirName, const struct nls_table *nls_codepage)
464 {
465         DELETE_DIRECTORY_REQ *pSMB = NULL;
466         DELETE_DIRECTORY_RSP *pSMBr = NULL;
467         int rc = 0;
468         int bytes_returned;
469         int name_len;
470
471         cFYI(1, ("In CIFSSMBRmDir"));
472 RmDirRetry:
473         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
474                       (void **) &pSMBr);
475         if (rc)
476                 return rc;
477
478         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
479                 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
480                                 /* find define for this maxpathcomponent */
481                                 , nls_codepage);
482                 name_len++;     /* trailing null */
483                 name_len *= 2;
484         } else {                /* BB improve the check for buffer overruns BB */
485                 name_len = strnlen(dirName, 530);
486                 name_len++;     /* trailing null */
487                 strncpy(pSMB->DirName, dirName, name_len);
488         }
489
490         pSMB->BufferFormat = 0x04;
491         pSMB->hdr.smb_buf_length += name_len + 1;
492         pSMB->ByteCount = cpu_to_le16(name_len + 1);
493         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
494                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
495         if (rc) {
496                 cFYI(1, ("Error in RMDir = %d", rc));
497         }
498 #ifdef CONFIG_CIFS_STATS
499         else {
500                 atomic_inc(&tcon->num_rmdirs);
501         }
502 #endif
503
504         if (pSMB)
505                 cifs_buf_release(pSMB);
506         if (rc == -EAGAIN)
507                 goto RmDirRetry;
508         return rc;
509 }
510
511 int
512 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
513              const char *name, const struct nls_table *nls_codepage)
514 {
515         int rc = 0;
516         CREATE_DIRECTORY_REQ *pSMB = NULL;
517         CREATE_DIRECTORY_RSP *pSMBr = NULL;
518         int bytes_returned;
519         int name_len;
520
521         cFYI(1, ("In CIFSSMBMkDir"));
522 MkDirRetry:
523         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
524                       (void **) &pSMBr);
525         if (rc)
526                 return rc;
527
528         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
529                 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
530                                          /* find define for this maxpathcomponent */
531                                          , nls_codepage);
532                 name_len++;     /* trailing null */
533                 name_len *= 2;
534         } else {                /* BB improve the check for buffer overruns BB */
535                 name_len = strnlen(name, 530);
536                 name_len++;     /* trailing null */
537                 strncpy(pSMB->DirName, name, name_len);
538         }
539
540         pSMB->BufferFormat = 0x04;
541         pSMB->hdr.smb_buf_length += name_len + 1;
542         pSMB->ByteCount = cpu_to_le16(name_len + 1);
543         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
544                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
545         if (rc) {
546                 cFYI(1, ("Error in Mkdir = %d", rc));
547         }
548 #ifdef CONFIG_CIFS_STATS
549         else {
550                 atomic_inc(&tcon->num_mkdirs);
551         }
552 #endif
553         if (pSMB)
554                 cifs_buf_release(pSMB);
555         if (rc == -EAGAIN)
556                 goto MkDirRetry;
557         return rc;
558 }
559
560 int
561 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
562             const char *fileName, const int openDisposition,
563             const int access_flags, const int create_options, __u16 * netfid,
564             int *pOplock, FILE_ALL_INFO * pfile_info, 
565             const struct nls_table *nls_codepage)
566 {
567         int rc = -EACCES;
568         OPEN_REQ *pSMB = NULL;
569         OPEN_RSP *pSMBr = NULL;
570         int bytes_returned;
571         int name_len;
572         __u16 count;
573
574 openRetry:
575         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
576                       (void **) &pSMBr);
577         if (rc)
578                 return rc;
579
580         pSMB->AndXCommand = 0xFF;       /* none */
581
582         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
583                 count = 1;      /* account for one byte pad to word boundary */
584                 name_len =
585                     cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
586                                   fileName, 530
587                                   /* find define for this maxpathcomponent */
588                                   , nls_codepage);
589                 name_len++;     /* trailing null */
590                 name_len *= 2;
591                 pSMB->NameLength = cpu_to_le16(name_len);
592         } else {                /* BB improve the check for buffer overruns BB */
593                 count = 0;      /* no pad */
594                 name_len = strnlen(fileName, 530);
595                 name_len++;     /* trailing null */
596                 pSMB->NameLength = cpu_to_le16(name_len);
597                 strncpy(pSMB->fileName, fileName, name_len);
598         }
599         if (*pOplock & REQ_OPLOCK)
600                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
601         else if (*pOplock & REQ_BATCHOPLOCK) {
602                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
603         }
604         pSMB->DesiredAccess = cpu_to_le32(access_flags);
605         pSMB->AllocationSize = 0;
606         pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
607         /* XP does not handle ATTR_POSIX_SEMANTICS */
608         /* but it helps speed up case sensitive checks for other
609         servers such as Samba */
610         if (tcon->ses->capabilities & CAP_UNIX)
611                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
612
613         /* if ((omode & S_IWUGO) == 0)
614                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
615         /*  Above line causes problems due to vfs splitting create into two
616                 pieces - need to set mode after file created not while it is
617                 being created */
618         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
619         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
620         pSMB->CreateOptions = cpu_to_le32(create_options);
621         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
622         pSMB->SecurityFlags =
623             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
624
625         count += name_len;
626         pSMB->hdr.smb_buf_length += count;
627
628         pSMB->ByteCount = cpu_to_le16(count);
629         /* long_op set to 1 to allow for oplock break timeouts */
630         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
631                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
632         if (rc) {
633                 cFYI(1, ("Error in Open = %d", rc));
634         } else {
635                 *pOplock = pSMBr->OplockLevel;  /* one byte no need to le_to_cpu */
636                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
637                 /* Let caller know file was created so we can set the mode. */
638                 /* Do we care about the CreateAction in any other cases? */
639                 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
640                         *pOplock |= CIFS_CREATE_ACTION; 
641                 if(pfile_info) {
642                     memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
643                         36 /* CreationTime to Attributes */);
644                     /* the file_info buf is endian converted by caller */
645                     pfile_info->AllocationSize = pSMBr->AllocationSize;
646                     pfile_info->EndOfFile = pSMBr->EndOfFile;
647                     pfile_info->NumberOfLinks = cpu_to_le32(1);
648                 }
649
650 #ifdef CONFIG_CIFS_STATS
651                 atomic_inc(&tcon->num_opens);
652 #endif
653         }
654         if (pSMB)
655                 cifs_buf_release(pSMB);
656         if (rc == -EAGAIN)
657                 goto openRetry;
658         return rc;
659 }
660
661 /* If no buffer passed in, then caller wants to do the copy
662         as in the case of readpages so the SMB buffer must be
663         freed by the caller */
664
665 int
666 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
667             const int netfid, const unsigned int count,
668             const __u64 lseek, unsigned int *nbytes, char **buf)
669 {
670         int rc = -EACCES;
671         READ_REQ *pSMB = NULL;
672         READ_RSP *pSMBr = NULL;
673         char *pReadData = NULL;
674         int bytes_returned;
675
676         *nbytes = 0;
677         rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
678                       (void **) &pSMBr);
679         if (rc)
680                 return rc;
681
682         /* tcon and ses pointer are checked in smb_init */
683         if (tcon->ses->server == NULL)
684                 return -ECONNABORTED;
685
686         pSMB->AndXCommand = 0xFF;       /* none */
687         pSMB->Fid = netfid;
688         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
689         pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
690         pSMB->Remaining = 0;
691         pSMB->MaxCount = cpu_to_le16(count);
692         pSMB->MaxCountHigh = 0;
693         pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
694
695         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
696                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
697         if (rc) {
698                 cERROR(1, ("Send error in read = %d", rc));
699         } else {
700                 __u16 data_length = le16_to_cpu(pSMBr->DataLength);
701                 *nbytes = data_length;
702                 /*check that DataLength would not go beyond end of SMB */
703                 if ((data_length > CIFS_MAX_MSGSIZE) 
704                                 || (data_length > count)) {
705                         cFYI(1,("bad length %d for count %d",data_length,count));
706                         rc = -EIO;
707                         *nbytes = 0;
708                 } else {
709                         pReadData =
710                             (char *) (&pSMBr->hdr.Protocol) +
711                             le16_to_cpu(pSMBr->DataOffset);
712 /*                      if(rc = copy_to_user(buf, pReadData, data_length)) {
713                                 cERROR(1,("Faulting on read rc = %d",rc));
714                                 rc = -EFAULT;
715                         }*/ /* can not use copy_to_user when using page cache*/
716                         if(*buf)
717                             memcpy(*buf,pReadData,data_length);
718                 }
719         }
720         if (pSMB) {
721                 if(*buf)
722                         cifs_buf_release(pSMB);
723                 else
724                         *buf = (char *)pSMB;
725         }
726
727         /* Note: On -EAGAIN error only caller can retry on handle based calls 
728                 since file handle passed in no longer valid */
729         return rc;
730 }
731
732 int
733 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
734              const int netfid, const unsigned int count,
735              const __u64 offset, unsigned int *nbytes, const char *buf,
736              const int long_op)
737 {
738         int rc = -EACCES;
739         WRITE_REQ *pSMB = NULL;
740         WRITE_RSP *pSMBr = NULL;
741         int bytes_returned;
742         unsigned bytes_sent;
743         __u16 byte_count;
744
745         rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
746                       (void **) &pSMBr);
747         if (rc)
748                 return rc;
749         /* tcon and ses pointer are checked in smb_init */
750         if (tcon->ses->server == NULL)
751                 return -ECONNABORTED;
752
753         pSMB->AndXCommand = 0xFF;       /* none */
754         pSMB->Fid = netfid;
755         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
756         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
757         pSMB->Remaining = 0;
758         bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
759         if (bytes_sent > count)
760                 bytes_sent = count;
761         pSMB->DataLengthHigh = 0;
762         pSMB->DataOffset =
763             cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
764
765         memcpy(pSMB->Data,buf,bytes_sent);
766
767         byte_count = bytes_sent + 1 /* pad */ ;
768         pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
769         pSMB->DataLengthHigh = 0;
770         pSMB->hdr.smb_buf_length += byte_count;
771         pSMB->ByteCount = cpu_to_le16(byte_count);
772
773         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
774                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
775         if (rc) {
776                 cFYI(1, ("Send error in write = %d", rc));
777                 *nbytes = 0;
778         } else
779                 *nbytes = le16_to_cpu(pSMBr->Count);
780
781         if (pSMB)
782                 cifs_buf_release(pSMB);
783
784         /* Note: On -EAGAIN error only caller can retry on handle based calls 
785                 since file handle passed in no longer valid */
786
787         return rc;
788 }
789
790 int
791 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
792             const __u16 smb_file_id, const __u64 len,
793             const __u64 offset, const __u32 numUnlock,
794             const __u32 numLock, const __u8 lockType, const int waitFlag)
795 {
796         int rc = 0;
797         LOCK_REQ *pSMB = NULL;
798         LOCK_RSP *pSMBr = NULL;
799         int bytes_returned;
800         int timeout = 0;
801         __u16 count;
802
803         cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
804         rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
805                       (void **) &pSMBr);
806         if (rc)
807                 return rc;
808
809         if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
810                 timeout = -1; /* no response expected */
811                 pSMB->Timeout = 0;
812         } else if (waitFlag == TRUE) {
813                 timeout = 3;  /* blocking operation, no timeout */
814                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
815         } else {
816                 pSMB->Timeout = 0;
817         }
818
819         pSMB->NumberOfLocks = cpu_to_le16(numLock);
820         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
821         pSMB->LockType = lockType;
822         pSMB->AndXCommand = 0xFF;       /* none */
823         pSMB->Fid = smb_file_id; /* netfid stays le */
824
825         if((numLock != 0) || (numUnlock != 0)) {
826                 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
827                 /* BB where to store pid high? */
828                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
829                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
830                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
831                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
832                 count = sizeof(LOCKING_ANDX_RANGE);
833         } else {
834                 /* oplock break */
835                 count = 0;
836         }
837         pSMB->hdr.smb_buf_length += count;
838         pSMB->ByteCount = cpu_to_le16(count);
839
840         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
841                          (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
842
843         if (rc) {
844                 cFYI(1, ("Send error in Lock = %d", rc));
845         }
846         if (pSMB)
847                 cifs_buf_release(pSMB);
848
849         /* Note: On -EAGAIN error only caller can retry on handle based calls 
850         since file handle passed in no longer valid */
851         return rc;
852 }
853
854 int
855 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
856 {
857         int rc = 0;
858         CLOSE_REQ *pSMB = NULL;
859         CLOSE_RSP *pSMBr = NULL;
860         int bytes_returned;
861         cFYI(1, ("In CIFSSMBClose"));
862
863 /* do not retry on dead session on close */
864         rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
865                       (void **) &pSMBr);
866         if(rc == -EAGAIN)
867                 return 0;
868         if (rc)
869                 return rc;
870
871         pSMB->FileID = (__u16) smb_file_id;
872         pSMB->LastWriteTime = 0;
873         pSMB->ByteCount = 0;
874         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
875                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
876         if (rc) {
877                 if(rc!=-EINTR) {
878                         /* EINTR is expected when user ctl-c to kill app */
879                         cERROR(1, ("Send error in Close = %d", rc));
880                 }
881         }
882         if (pSMB)
883                 cifs_buf_release(pSMB);
884
885         /* Since session is dead, file will be closed on server already */
886         if(rc == -EAGAIN)
887                 rc = 0;
888
889         return rc;
890 }
891
892 int
893 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
894               const char *fromName, const char *toName,
895               const struct nls_table *nls_codepage)
896 {
897         int rc = 0;
898         RENAME_REQ *pSMB = NULL;
899         RENAME_RSP *pSMBr = NULL;
900         int bytes_returned;
901         int name_len, name_len2;
902         __u16 count;
903
904         cFYI(1, ("In CIFSSMBRename"));
905 renameRetry:
906         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
907                       (void **) &pSMBr);
908         if (rc)
909                 return rc;
910
911         pSMB->BufferFormat = 0x04;
912         pSMB->SearchAttributes =
913             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
914                         ATTR_DIRECTORY);
915
916         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
917                 name_len =
918                     cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
919                                   /* find define for this maxpathcomponent */
920                                   , nls_codepage);
921                 name_len++;     /* trailing null */
922                 name_len *= 2;
923                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
924         /* protocol requires ASCII signature byte on Unicode string */
925                 pSMB->OldFileName[name_len + 1] = 0x00;
926                 name_len2 =
927                     cifs_strtoUCS((wchar_t *) & pSMB->
928                                   OldFileName[name_len + 2], toName, 530,
929                                   nls_codepage);
930                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
931                 name_len2 *= 2; /* convert to bytes */
932         } else {                /* BB improve the check for buffer overruns BB */
933                 name_len = strnlen(fromName, 530);
934                 name_len++;     /* trailing null */
935                 strncpy(pSMB->OldFileName, fromName, name_len);
936                 name_len2 = strnlen(toName, 530);
937                 name_len2++;    /* trailing null */
938                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
939                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
940                 name_len2++;    /* trailing null */
941                 name_len2++;    /* signature byte */
942         }
943
944         count = 1 /* 1st signature byte */  + name_len + name_len2;
945         pSMB->hdr.smb_buf_length += count;
946         pSMB->ByteCount = cpu_to_le16(count);
947
948         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
949                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
950         if (rc) {
951                 cFYI(1, ("Send error in rename = %d", rc));
952         } 
953
954 #ifdef CONFIG_CIFS_STATS
955           else {
956                 atomic_inc(&tcon->num_renames);
957         }
958 #endif
959
960         if (pSMB)
961                 cifs_buf_release(pSMB);
962
963         if (rc == -EAGAIN)
964                 goto renameRetry;
965
966         return rc;
967 }
968
969 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 
970                 int netfid, char * target_name, const struct nls_table * nls_codepage) 
971 {
972         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
973         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
974         struct set_file_rename * rename_info;
975         char *data_offset;
976         char dummy_string[30];
977         int rc = 0;
978         int bytes_returned = 0;
979         int len_of_str;
980         __u16 params, param_offset, offset, count, byte_count;
981
982         cFYI(1, ("Rename to File by handle"));
983         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
984                         (void **) &pSMBr);
985         if (rc)
986                 return rc;
987
988         params = 6;
989         pSMB->MaxSetupCount = 0;
990         pSMB->Reserved = 0;
991         pSMB->Flags = 0;
992         pSMB->Timeout = 0;
993         pSMB->Reserved2 = 0;
994         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
995         offset = param_offset + params;
996
997         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
998         rename_info = (struct set_file_rename *) data_offset;
999         pSMB->MaxParameterCount = cpu_to_le16(2);
1000         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1001         pSMB->SetupCount = 1;
1002         pSMB->Reserved3 = 0;
1003         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1004         byte_count = 3 /* pad */  + params;
1005         pSMB->ParameterCount = cpu_to_le16(params);
1006         pSMB->TotalParameterCount = pSMB->ParameterCount;
1007         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1008         pSMB->DataOffset = cpu_to_le16(offset);
1009         /* construct random name ".cifs_tmp<inodenum><mid>" */
1010         rename_info->overwrite = cpu_to_le32(1);
1011         rename_info->root_fid  = 0;
1012         /* unicode only call */
1013         if(target_name == NULL) {
1014                 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1015                 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1016         } else {
1017                 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
1018         }
1019         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1020         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1021         byte_count += count;
1022         pSMB->DataCount = cpu_to_le16(count);
1023         pSMB->TotalDataCount = pSMB->DataCount;
1024         pSMB->Fid = netfid;
1025         pSMB->InformationLevel =
1026                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1027         pSMB->Reserved4 = 0;
1028         pSMB->hdr.smb_buf_length += byte_count;
1029         pSMB->ByteCount = cpu_to_le16(byte_count);
1030         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1031                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1032         if (rc) {
1033                 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1034         }
1035 #ifdef CONFIG_CIFS_STATS
1036           else {
1037                 atomic_inc(&pTcon->num_t2renames);
1038         }
1039 #endif
1040         if (pSMB)
1041                 cifs_buf_release(pSMB);
1042
1043         /* Note: On -EAGAIN error only caller can retry on handle based calls
1044                 since file handle passed in no longer valid */
1045
1046         return rc;
1047 }
1048
1049 int
1050 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
1051             const __u16 target_tid, const char *toName, const int flags,
1052             const struct nls_table *nls_codepage)
1053 {
1054         int rc = 0;
1055         COPY_REQ *pSMB = NULL;
1056         COPY_RSP *pSMBr = NULL;
1057         int bytes_returned;
1058         int name_len, name_len2;
1059         __u16 count;
1060
1061         cFYI(1, ("In CIFSSMBCopy"));
1062 copyRetry:
1063         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1064                         (void **) &pSMBr);
1065         if (rc)
1066                 return rc;
1067
1068         pSMB->BufferFormat = 0x04;
1069         pSMB->Tid2 = target_tid;
1070
1071         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1072
1073         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1074                 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
1075                                 fromName, 
1076                                 530 /* find define for this maxpathcomponent */,
1077                                 nls_codepage);
1078                 name_len++;     /* trailing null */
1079                 name_len *= 2;
1080                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1081                 /* protocol requires ASCII signature byte on Unicode string */
1082                 pSMB->OldFileName[name_len + 1] = 0x00;
1083                 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1084                                 OldFileName[name_len + 2], toName, 530,
1085                                 nls_codepage);
1086                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1087                 name_len2 *= 2; /* convert to bytes */
1088         } else {                /* BB improve the check for buffer overruns BB */
1089                 name_len = strnlen(fromName, 530);
1090                 name_len++;     /* trailing null */
1091                 strncpy(pSMB->OldFileName, fromName, name_len);
1092                 name_len2 = strnlen(toName, 530);
1093                 name_len2++;    /* trailing null */
1094                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
1095                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1096                 name_len2++;    /* trailing null */
1097                 name_len2++;    /* signature byte */
1098         }
1099
1100         count = 1 /* 1st signature byte */  + name_len + name_len2;
1101         pSMB->hdr.smb_buf_length += count;
1102         pSMB->ByteCount = cpu_to_le16(count);
1103
1104         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1105                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1106         if (rc) {
1107                 cFYI(1, ("Send error in copy = %d with %d files copied",
1108                         rc, le16_to_cpu(pSMBr->CopyCount)));
1109         }
1110         if (pSMB)
1111                 cifs_buf_release(pSMB);
1112
1113         if (rc == -EAGAIN)
1114                 goto copyRetry;
1115
1116         return rc;
1117 }
1118
1119 int
1120 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1121                       const char *fromName, const char *toName,
1122                       const struct nls_table *nls_codepage)
1123 {
1124         TRANSACTION2_SPI_REQ *pSMB = NULL;
1125         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1126         char *data_offset;
1127         int name_len;
1128         int name_len_target;
1129         int rc = 0;
1130         int bytes_returned = 0;
1131         __u16 params, param_offset, offset, byte_count;
1132
1133         cFYI(1, ("In Symlink Unix style"));
1134 createSymLinkRetry:
1135         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1136                       (void **) &pSMBr);
1137         if (rc)
1138                 return rc;
1139
1140         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1141                 name_len =
1142                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
1143                                   /* find define for this maxpathcomponent */
1144                                   , nls_codepage);
1145                 name_len++;     /* trailing null */
1146                 name_len *= 2;
1147
1148         } else {                /* BB improve the check for buffer overruns BB */
1149                 name_len = strnlen(fromName, 530);
1150                 name_len++;     /* trailing null */
1151                 strncpy(pSMB->FileName, fromName, name_len);
1152         }
1153         params = 6 + name_len;
1154         pSMB->MaxSetupCount = 0;
1155         pSMB->Reserved = 0;
1156         pSMB->Flags = 0;
1157         pSMB->Timeout = 0;
1158         pSMB->Reserved2 = 0;
1159         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1160                                      InformationLevel) - 4;
1161         offset = param_offset + params;
1162
1163         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1164         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1165                 name_len_target =
1166                     cifs_strtoUCS((wchar_t *) data_offset, toName, 530
1167                                   /* find define for this maxpathcomponent */
1168                                   , nls_codepage);
1169                 name_len_target++;      /* trailing null */
1170                 name_len_target *= 2;
1171         } else {                /* BB improve the check for buffer overruns BB */
1172                 name_len_target = strnlen(toName, 530);
1173                 name_len_target++;      /* trailing null */
1174                 strncpy(data_offset, toName, name_len_target);
1175         }
1176
1177         pSMB->MaxParameterCount = cpu_to_le16(2);
1178         /* BB find exact max on data count below from sess */
1179         pSMB->MaxDataCount = cpu_to_le16(1000);
1180         pSMB->SetupCount = 1;
1181         pSMB->Reserved3 = 0;
1182         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1183         byte_count = 3 /* pad */  + params + name_len_target;
1184         pSMB->DataCount = cpu_to_le16(name_len_target);
1185         pSMB->ParameterCount = cpu_to_le16(params);
1186         pSMB->TotalDataCount = pSMB->DataCount;
1187         pSMB->TotalParameterCount = pSMB->ParameterCount;
1188         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1189         pSMB->DataOffset = cpu_to_le16(offset);
1190         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1191         pSMB->Reserved4 = 0;
1192         pSMB->hdr.smb_buf_length += byte_count;
1193         pSMB->ByteCount = cpu_to_le16(byte_count);
1194         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1195                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1196         if (rc) {
1197                 cFYI(1,
1198                      ("Send error in SetPathInfo (create symlink) = %d",
1199                       rc));
1200         }
1201
1202         if (pSMB)
1203                 cifs_buf_release(pSMB);
1204
1205         if (rc == -EAGAIN)
1206                 goto createSymLinkRetry;
1207
1208         return rc;
1209 }
1210
1211 int
1212 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1213                        const char *fromName, const char *toName,
1214                        const struct nls_table *nls_codepage)
1215 {
1216         TRANSACTION2_SPI_REQ *pSMB = NULL;
1217         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1218         char *data_offset;
1219         int name_len;
1220         int name_len_target;
1221         int rc = 0;
1222         int bytes_returned = 0;
1223         __u16 params, param_offset, offset, byte_count;
1224
1225         cFYI(1, ("In Create Hard link Unix style"));
1226 createHardLinkRetry:
1227         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1228                       (void **) &pSMBr);
1229         if (rc)
1230                 return rc;
1231
1232         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1233                 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
1234                                          /* find define for this maxpathcomponent */
1235                                          , nls_codepage);
1236                 name_len++;     /* trailing null */
1237                 name_len *= 2;
1238
1239         } else {                /* BB improve the check for buffer overruns BB */
1240                 name_len = strnlen(toName, 530);
1241                 name_len++;     /* trailing null */
1242                 strncpy(pSMB->FileName, toName, name_len);
1243         }
1244         params = 6 + name_len;
1245         pSMB->MaxSetupCount = 0;
1246         pSMB->Reserved = 0;
1247         pSMB->Flags = 0;
1248         pSMB->Timeout = 0;
1249         pSMB->Reserved2 = 0;
1250         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1251                                      InformationLevel) - 4;
1252         offset = param_offset + params;
1253
1254         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1255         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1256                 name_len_target =
1257                     cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
1258                                   /* find define for this maxpathcomponent */
1259                                   , nls_codepage);
1260                 name_len_target++;      /* trailing null */
1261                 name_len_target *= 2;
1262         } else {                /* BB improve the check for buffer overruns BB */
1263                 name_len_target = strnlen(fromName, 530);
1264                 name_len_target++;      /* trailing null */
1265                 strncpy(data_offset, fromName, name_len_target);
1266         }
1267
1268         pSMB->MaxParameterCount = cpu_to_le16(2);
1269         /* BB find exact max on data count below from sess*/
1270         pSMB->MaxDataCount = cpu_to_le16(1000);
1271         pSMB->SetupCount = 1;
1272         pSMB->Reserved3 = 0;
1273         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1274         byte_count = 3 /* pad */  + params + name_len_target;
1275         pSMB->ParameterCount = cpu_to_le16(params);
1276         pSMB->TotalParameterCount = pSMB->ParameterCount;
1277         pSMB->DataCount = cpu_to_le16(name_len_target);
1278         pSMB->TotalDataCount = pSMB->DataCount;
1279         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1280         pSMB->DataOffset = cpu_to_le16(offset);
1281         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1282         pSMB->Reserved4 = 0;
1283         pSMB->hdr.smb_buf_length += byte_count;
1284         pSMB->ByteCount = cpu_to_le16(byte_count);
1285         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1286                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1287         if (rc) {
1288                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1289         }
1290
1291         if (pSMB)
1292                 cifs_buf_release(pSMB);
1293         if (rc == -EAGAIN)
1294                 goto createHardLinkRetry;
1295
1296         return rc;
1297 }
1298
1299 int
1300 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1301                    const char *fromName, const char *toName,
1302                    const struct nls_table *nls_codepage)
1303 {
1304         int rc = 0;
1305         NT_RENAME_REQ *pSMB = NULL;
1306         RENAME_RSP *pSMBr = NULL;
1307         int bytes_returned;
1308         int name_len, name_len2;
1309         __u16 count;
1310
1311         cFYI(1, ("In CIFSCreateHardLink"));
1312 winCreateHardLinkRetry:
1313
1314         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1315                       (void **) &pSMBr);
1316         if (rc)
1317                 return rc;
1318
1319         pSMB->SearchAttributes =
1320             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1321                         ATTR_DIRECTORY);
1322         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1323         pSMB->ClusterCount = 0;
1324
1325         pSMB->BufferFormat = 0x04;
1326
1327         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1328                 name_len =
1329                     cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
1330                                   /* find define for this maxpathcomponent */
1331                                   , nls_codepage);
1332                 name_len++;     /* trailing null */
1333                 name_len *= 2;
1334                 pSMB->OldFileName[name_len] = 0;        /* pad */
1335                 pSMB->OldFileName[name_len + 1] = 0x04; 
1336                 name_len2 =
1337                     cifs_strtoUCS((wchar_t *) & pSMB->
1338                                   OldFileName[name_len + 2], toName, 530,
1339                                   nls_codepage);
1340                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1341                 name_len2 *= 2; /* convert to bytes */
1342         } else {                /* BB improve the check for buffer overruns BB */
1343                 name_len = strnlen(fromName, 530);
1344                 name_len++;     /* trailing null */
1345                 strncpy(pSMB->OldFileName, fromName, name_len);
1346                 name_len2 = strnlen(toName, 530);
1347                 name_len2++;    /* trailing null */
1348                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
1349                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1350                 name_len2++;    /* trailing null */
1351                 name_len2++;    /* signature byte */
1352         }
1353
1354         count = 1 /* string type byte */  + name_len + name_len2;
1355         pSMB->hdr.smb_buf_length += count;
1356         pSMB->ByteCount = cpu_to_le16(count);
1357
1358         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1359                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1360         if (rc) {
1361                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1362         }
1363         if (pSMB)
1364                 cifs_buf_release(pSMB);
1365         if (rc == -EAGAIN)
1366                 goto winCreateHardLinkRetry;
1367
1368         return rc;
1369 }
1370
1371 int
1372 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1373                         const unsigned char *searchName,
1374                         char *symlinkinfo, const int buflen,
1375                         const struct nls_table *nls_codepage)
1376 {
1377 /* SMB_QUERY_FILE_UNIX_LINK */
1378         TRANSACTION2_QPI_REQ *pSMB = NULL;
1379         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1380         int rc = 0;
1381         int bytes_returned;
1382         int name_len;
1383         __u16 params, byte_count;
1384
1385         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1386
1387 querySymLinkRetry:
1388         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1389                       (void **) &pSMBr);
1390         if (rc)
1391                 return rc;
1392
1393         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1394                 name_len =
1395                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1396                                   /* find define for this maxpathcomponent */
1397                                   , nls_codepage);
1398                 name_len++;     /* trailing null */
1399                 name_len *= 2;
1400         } else {                /* BB improve the check for buffer overruns BB */
1401                 name_len = strnlen(searchName, 530);
1402                 name_len++;     /* trailing null */
1403                 strncpy(pSMB->FileName, searchName, name_len);
1404         }
1405
1406         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
1407         pSMB->TotalDataCount = 0;
1408         pSMB->MaxParameterCount = cpu_to_le16(2);
1409         /* BB find exact max data count below from sess structure BB */
1410         pSMB->MaxDataCount = cpu_to_le16(4000);
1411         pSMB->MaxSetupCount = 0;
1412         pSMB->Reserved = 0;
1413         pSMB->Flags = 0;
1414         pSMB->Timeout = 0;
1415         pSMB->Reserved2 = 0;
1416         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1417         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1418         pSMB->DataCount = 0;
1419         pSMB->DataOffset = 0;
1420         pSMB->SetupCount = 1;
1421         pSMB->Reserved3 = 0;
1422         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1423         byte_count = params + 1 /* pad */ ;
1424         pSMB->TotalParameterCount = cpu_to_le16(params);
1425         pSMB->ParameterCount = pSMB->TotalParameterCount;
1426         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1427         pSMB->Reserved4 = 0;
1428         pSMB->hdr.smb_buf_length += byte_count;
1429         pSMB->ByteCount = cpu_to_le16(byte_count);
1430
1431         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1432                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1433         if (rc) {
1434                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1435         } else {                /* decode response */
1436                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
1437                 __u16 count = le16_to_cpu(pSMBr->DataCount);
1438                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1439                 /* BB also check enough total bytes returned */
1440                         rc = -EIO;      /* bad smb */
1441                 else {
1442                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1443                                 name_len = UniStrnlen((wchar_t *) ((char *)
1444                                         &pSMBr->hdr.Protocol +data_offset),
1445                                         min_t(const int, buflen,count) / 2);
1446                                 cifs_strfromUCS_le(symlinkinfo,
1447                                         (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1448                                                 data_offset),
1449                                         name_len, nls_codepage);
1450                         } else {
1451                                 strncpy(symlinkinfo,
1452                                         (char *) &pSMBr->hdr.Protocol + 
1453                                                 data_offset,
1454                                         min_t(const int, buflen, count));
1455                         }
1456                         symlinkinfo[buflen] = 0;
1457         /* just in case so calling code does not go off the end of buffer */
1458                 }
1459         }
1460         if (pSMB)
1461                 cifs_buf_release(pSMB);
1462         if (rc == -EAGAIN)
1463                 goto querySymLinkRetry;
1464         return rc;
1465 }
1466
1467
1468
1469 int
1470 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1471                         const unsigned char *searchName,
1472                         char *symlinkinfo, const int buflen,__u16 fid,
1473                         const struct nls_table *nls_codepage)
1474 {
1475         int rc = 0;
1476         int bytes_returned;
1477         int name_len;
1478         struct smb_com_transaction_ioctl_req * pSMB;
1479         struct smb_com_transaction_ioctl_rsp * pSMBr;
1480
1481         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1482         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1483                       (void **) &pSMBr);
1484         if (rc)
1485                 return rc;
1486
1487         pSMB->TotalParameterCount = 0 ;
1488         pSMB->TotalDataCount = 0;
1489         pSMB->MaxParameterCount = cpu_to_le32(2);
1490         /* BB find exact data count max from sess structure BB */
1491         pSMB->MaxDataCount = cpu_to_le32(4000);
1492         pSMB->MaxSetupCount = 4;
1493         pSMB->Reserved = 0;
1494         pSMB->ParameterOffset = 0;
1495         pSMB->DataCount = 0;
1496         pSMB->DataOffset = 0;
1497         pSMB->SetupCount = 4;
1498         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1499         pSMB->ParameterCount = pSMB->TotalParameterCount;
1500         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1501         pSMB->IsFsctl = 1; /* FSCTL */
1502         pSMB->IsRootFlag = 0;
1503         pSMB->Fid = fid; /* file handle always le */
1504         pSMB->ByteCount = 0;
1505
1506         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1507                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1508         if (rc) {
1509                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1510         } else {                /* decode response */
1511                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1512                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1513                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1514                 /* BB also check enough total bytes returned */
1515                         rc = -EIO;      /* bad smb */
1516                 else {
1517                         if(data_count && (data_count < 2048)) {
1518                 /* could also validate reparse tag && better check name length */
1519                                 struct reparse_data * reparse_buf = (struct reparse_data *)
1520                                         ((char *)&pSMBr->hdr.Protocol + data_offset);
1521                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1522                                         name_len = UniStrnlen((wchar_t *)
1523                                                         (reparse_buf->LinkNamesBuf + 
1524                                                         reparse_buf->TargetNameOffset),
1525                                                         min(buflen/2, reparse_buf->TargetNameLen / 2)); 
1526                                         cifs_strfromUCS_le(symlinkinfo,
1527                                                 (wchar_t *) (reparse_buf->LinkNamesBuf + 
1528                                                 reparse_buf->TargetNameOffset),
1529                                                 name_len, nls_codepage);
1530                                 } else { /* ASCII names */
1531                                         strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + 
1532                                                 reparse_buf->TargetNameOffset, 
1533                                                 min_t(const int, buflen, reparse_buf->TargetNameLen));
1534                                 }
1535                         } else {
1536                                 rc = -EIO;
1537                                 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1538                         }
1539                         symlinkinfo[buflen] = 0; /* just in case so the caller
1540                                         does not go off the end of the buffer */
1541                         cFYI(1,("readlink result - %s ",symlinkinfo));
1542                 }
1543         }
1544         if (pSMB)
1545                 cifs_buf_release(pSMB);
1546
1547         /* Note: On -EAGAIN error only caller can retry on handle based calls
1548                 since file handle passed in no longer valid */
1549
1550         return rc;
1551 }
1552
1553 int
1554 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1555                  const unsigned char *searchName,
1556                  FILE_ALL_INFO * pFindData,
1557                  const struct nls_table *nls_codepage)
1558 {
1559 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1560         TRANSACTION2_QPI_REQ *pSMB = NULL;
1561         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1562         int rc = 0;
1563         int bytes_returned;
1564         int name_len;
1565         __u16 params, byte_count;
1566
1567         cFYI(1, ("In QPathInfo path %s", searchName));
1568 QPathInfoRetry:
1569         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1570                       (void **) &pSMBr);
1571         if (rc)
1572                 return rc;
1573
1574         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1575                 name_len =
1576                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1577                                   /* find define for this maxpathcomponent */
1578                                   , nls_codepage);
1579                 name_len++;     /* trailing null */
1580                 name_len *= 2;
1581         } else {                /* BB improve the check for buffer overruns BB */
1582                 name_len = strnlen(searchName, 530);
1583                 name_len++;     /* trailing null */
1584                 strncpy(pSMB->FileName, searchName, name_len);
1585         }
1586
1587         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
1588         pSMB->TotalDataCount = 0;
1589         pSMB->MaxParameterCount = cpu_to_le16(2);
1590         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1591         pSMB->MaxSetupCount = 0;
1592         pSMB->Reserved = 0;
1593         pSMB->Flags = 0;
1594         pSMB->Timeout = 0;
1595         pSMB->Reserved2 = 0;
1596         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1597         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1598         pSMB->DataCount = 0;
1599         pSMB->DataOffset = 0;
1600         pSMB->SetupCount = 1;
1601         pSMB->Reserved3 = 0;
1602         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1603         byte_count = params + 1 /* pad */ ;
1604         pSMB->TotalParameterCount = cpu_to_le16(params);
1605         pSMB->ParameterCount = pSMB->TotalParameterCount;
1606         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1607         pSMB->Reserved4 = 0;
1608         pSMB->hdr.smb_buf_length += byte_count;
1609         pSMB->ByteCount = cpu_to_le16(byte_count);
1610
1611         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1612                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1613         if (rc) {
1614                 cFYI(1, ("Send error in QPathInfo = %d", rc));
1615         } else {                /* decode response */
1616                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
1617                 /* BB also check enough total bytes returned */
1618                 /* BB we need to improve the validity checking
1619                 of these trans2 responses */
1620                 if ((pSMBr->ByteCount < 40) || (data_offset > 512)) 
1621                         rc = -EIO;      /* bad smb */
1622                 else if (pFindData){
1623                         memcpy((char *) pFindData,
1624                                (char *) &pSMBr->hdr.Protocol +
1625                                data_offset, sizeof (FILE_ALL_INFO));
1626                 } else
1627                     rc = -ENOMEM;
1628         }
1629         if (pSMB)
1630                 cifs_buf_release(pSMB);
1631         if (rc == -EAGAIN)
1632                 goto QPathInfoRetry;
1633
1634         return rc;
1635 }
1636
1637 int
1638 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1639                      const unsigned char *searchName,
1640                      FILE_UNIX_BASIC_INFO * pFindData,
1641                      const struct nls_table *nls_codepage)
1642 {
1643 /* SMB_QUERY_FILE_UNIX_BASIC */
1644         TRANSACTION2_QPI_REQ *pSMB = NULL;
1645         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1646         int rc = 0;
1647         int bytes_returned = 0;
1648         int name_len;
1649         __u16 params, byte_count;
1650
1651         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1652 UnixQPathInfoRetry:
1653         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1654                       (void **) &pSMBr);
1655         if (rc)
1656                 return rc;
1657
1658         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1659                 name_len =
1660                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1661                                   /* find define for this maxpathcomponent */
1662                                   , nls_codepage);
1663                 name_len++;     /* trailing null */
1664                 name_len *= 2;
1665         } else {                /* BB improve the check for buffer overruns BB */
1666                 name_len = strnlen(searchName, 530);
1667                 name_len++;     /* trailing null */
1668                 strncpy(pSMB->FileName, searchName, name_len);
1669         }
1670
1671         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
1672         pSMB->TotalDataCount = 0;
1673         pSMB->MaxParameterCount = cpu_to_le16(2);
1674         /* BB find exact max SMB PDU from sess structure BB */
1675         pSMB->MaxDataCount = cpu_to_le16(4000); 
1676         pSMB->MaxSetupCount = 0;
1677         pSMB->Reserved = 0;
1678         pSMB->Flags = 0;
1679         pSMB->Timeout = 0;
1680         pSMB->Reserved2 = 0;
1681         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1682         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1683         pSMB->DataCount = 0;
1684         pSMB->DataOffset = 0;
1685         pSMB->SetupCount = 1;
1686         pSMB->Reserved3 = 0;
1687         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1688         byte_count = params + 1 /* pad */ ;
1689         pSMB->TotalParameterCount = cpu_to_le16(params);
1690         pSMB->ParameterCount = pSMB->TotalParameterCount;
1691         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1692         pSMB->Reserved4 = 0;
1693         pSMB->hdr.smb_buf_length += byte_count;
1694         pSMB->ByteCount = cpu_to_le16(byte_count);
1695
1696         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1697                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1698         if (rc) {
1699                 cFYI(1, ("Send error in QPathInfo = %d", rc));
1700         } else {                /* decode response */
1701                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
1702                 /* BB also check if enough total bytes returned */
1703                 if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || 
1704                         (data_offset > 512) || 
1705                         (data_offset < sizeof(struct smb_hdr))) {
1706                         cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
1707                                         (int)data_offset,bytes_returned));
1708                         rc = -EIO;      /* bad smb */
1709                 } else {
1710                         memcpy((char *) pFindData,
1711                                (char *) &pSMBr->hdr.Protocol +
1712                                data_offset,
1713                                sizeof (FILE_UNIX_BASIC_INFO));
1714                 }
1715         }
1716         if (pSMB)
1717                 cifs_buf_release(pSMB);
1718         if (rc == -EAGAIN)
1719                 goto UnixQPathInfoRetry;
1720
1721         return rc;
1722 }
1723
1724 int
1725 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1726                const char *searchName, FILE_ALL_INFO * findData,
1727                const struct nls_table *nls_codepage)
1728 {
1729 /* level 257 SMB_ */
1730         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1731         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1732         int rc = 0;
1733         int bytes_returned;
1734         int name_len;
1735         __u16 params, byte_count;
1736
1737         cFYI(1, ("In FindUnique"));
1738 findUniqueRetry:
1739         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1740                       (void **) &pSMBr);
1741         if (rc)
1742                 return rc;
1743
1744         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1745                 name_len =
1746                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1747                                   /* find define for this maxpathcomponent */
1748                                   , nls_codepage);
1749                 name_len++;     /* trailing null */
1750                 name_len *= 2;
1751         } else {                /* BB improve the check for buffer overruns BB */
1752                 name_len = strnlen(searchName, 530);
1753                 name_len++;     /* trailing null */
1754                 strncpy(pSMB->FileName, searchName, name_len);
1755         }
1756
1757         params = 12 + name_len /* includes null */ ;
1758         pSMB->TotalDataCount = 0;       /* no EAs */
1759         pSMB->MaxParameterCount = cpu_to_le16(2);
1760         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1761         pSMB->MaxSetupCount = 0;
1762         pSMB->Reserved = 0;
1763         pSMB->Flags = 0;
1764         pSMB->Timeout = 0;
1765         pSMB->Reserved2 = 0;
1766         pSMB->ParameterOffset = cpu_to_le16(
1767         offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1768         pSMB->DataCount = 0;
1769         pSMB->DataOffset = 0;
1770         pSMB->SetupCount = 1;   /* one byte, no need to le convert */
1771         pSMB->Reserved3 = 0;
1772         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1773         byte_count = params + 1 /* pad */ ;
1774         pSMB->TotalParameterCount = cpu_to_le16(params);
1775         pSMB->ParameterCount = pSMB->TotalParameterCount;
1776         pSMB->SearchAttributes =
1777             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1778                         ATTR_DIRECTORY);
1779         pSMB->SearchCount = cpu_to_le16(16);    /* BB increase */
1780         pSMB->SearchFlags = cpu_to_le16(1);
1781         pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1782         pSMB->SearchStorageType = 0;    /* BB what should we set this to? BB */
1783         pSMB->hdr.smb_buf_length += byte_count;
1784         pSMB->ByteCount = cpu_to_le16(byte_count);
1785
1786         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1787                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1788
1789         if (rc) {
1790                 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1791         } else {                /* decode response */
1792
1793                 /* BB fill in */
1794         }
1795         if (pSMB)
1796                 cifs_buf_release(pSMB);
1797         if (rc == -EAGAIN)
1798                 goto findUniqueRetry;
1799
1800         return rc;
1801 }
1802
1803 int
1804 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1805               const char *searchName, FILE_DIRECTORY_INFO * findData,
1806               T2_FFIRST_RSP_PARMS * findParms,
1807               const struct nls_table *nls_codepage, int *pUnicodeFlag,
1808               int *pUnixFlag)
1809 {
1810 /* level 257 SMB_ */
1811         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1812         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1813         char *response_data;
1814         int rc = 0;
1815         int bytes_returned;
1816         int name_len;
1817         __u16 params, byte_count;
1818
1819         cFYI(1, ("In FindFirst"));
1820 findFirstRetry:
1821         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1822                       (void **) &pSMBr);
1823         if (rc)
1824                 return rc;
1825
1826         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1827                 name_len =
1828                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1829                                   /* find define for this maxpathcomponent */
1830                                   , nls_codepage);
1831                 name_len++;     /* trailing null */
1832                 name_len *= 2;
1833         } else {                /* BB improve the check for buffer overruns BB */
1834                 name_len = strnlen(searchName, 530);
1835                 name_len++;     /* trailing null */
1836                 strncpy(pSMB->FileName, searchName, name_len);
1837         }
1838
1839         params = 12 + name_len /* includes null */ ;
1840         pSMB->TotalDataCount = 0;       /* no EAs */
1841         pSMB->MaxParameterCount = cpu_to_le16(10);
1842         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1843                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1844         pSMB->MaxSetupCount = 0;
1845         pSMB->Reserved = 0;
1846         pSMB->Flags = 0;
1847         pSMB->Timeout = 0;
1848         pSMB->Reserved2 = 0;
1849         byte_count = params + 1 /* pad */ ;
1850         pSMB->TotalParameterCount = cpu_to_le16(params);
1851         pSMB->ParameterCount = pSMB->TotalParameterCount;
1852         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
1853         smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1854         pSMB->DataCount = 0;
1855         pSMB->DataOffset = 0;
1856         pSMB->SetupCount = 1;   /* one byte no need to make endian neutral */
1857         pSMB->Reserved3 = 0;
1858         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1859         pSMB->SearchAttributes =
1860             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1861                         ATTR_DIRECTORY);
1862         pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));       /* should this be shrunk even more ? */
1863         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1864
1865         /* test for Unix extensions */
1866         if (tcon->ses->capabilities & CAP_UNIX) {
1867                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1868                 *pUnixFlag = TRUE;
1869         } else {
1870                 pSMB->InformationLevel =
1871                     cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1872                 *pUnixFlag = FALSE;
1873         }
1874         pSMB->SearchStorageType = 0;    /* BB what should we set this to? It is not clear if it matters BB */
1875         pSMB->hdr.smb_buf_length += byte_count;
1876         pSMB->ByteCount = cpu_to_le16(byte_count);
1877
1878         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1879                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1880
1881         if (rc) {               /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1882                 cFYI(1, ("Error in FindFirst = %d", rc));
1883         } else {                /* decode response */
1884                 /* BB add safety checks for these memcpys */
1885                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1886                         *pUnicodeFlag = TRUE;
1887                 else
1888                         *pUnicodeFlag = FALSE;
1889                 memcpy(findParms,
1890                        (char *) &pSMBr->hdr.Protocol +
1891                        le16_to_cpu(pSMBr->ParameterOffset),
1892                        sizeof (T2_FFIRST_RSP_PARMS));
1893                 response_data =
1894                     (char *) &pSMBr->hdr.Protocol +
1895                     le16_to_cpu(pSMBr->DataOffset);
1896                 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1897         }
1898         if (pSMB)
1899                 cifs_buf_release(pSMB);
1900
1901         if (rc == -EAGAIN)
1902                 goto findFirstRetry;
1903
1904         return rc;
1905 }
1906
1907 int
1908 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1909                 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1910                 const __u16 searchHandle, char * resume_file_name, int name_len,
1911                 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1912 {
1913 /* level 257 SMB_ */
1914         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1915         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1916         char *response_data;
1917         int rc = 0;
1918         int bytes_returned;
1919         __u16 params, byte_count;
1920
1921         cFYI(1, ("In FindNext"));
1922
1923         if(resume_file_name == NULL) {
1924                 return -EIO;
1925         }
1926         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1927                       (void **) &pSMBr);
1928         if (rc)
1929                 return rc;
1930
1931         params = 14;    /* includes 2 bytes of null string, converted to LE below */
1932         byte_count = 0;
1933         pSMB->TotalDataCount = 0;       /* no EAs */
1934         pSMB->MaxParameterCount = cpu_to_le16(8);
1935         pSMB->MaxDataCount =
1936             cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1937         pSMB->MaxSetupCount = 0;
1938         pSMB->Reserved = 0;
1939         pSMB->Flags = 0;
1940         pSMB->Timeout = 0;
1941         pSMB->Reserved2 = 0;
1942         pSMB->ParameterOffset =  cpu_to_le16(offsetof(
1943         struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1944         pSMB->DataCount = 0;
1945         pSMB->DataOffset = 0;
1946         pSMB->SetupCount = 1;
1947         pSMB->Reserved3 = 0;
1948         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1949         pSMB->SearchHandle = searchHandle;      /* always kept as le */
1950         findParms->SearchCount = 0;     /* set to zero in case of error */
1951         pSMB->SearchCount =
1952             cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1953         /* test for Unix extensions */
1954         if (tcon->ses->capabilities & CAP_UNIX) {
1955                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1956                 *pUnixFlag = TRUE;
1957         } else {
1958                 pSMB->InformationLevel =
1959                     cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1960                 *pUnixFlag = FALSE;
1961         }
1962         pSMB->ResumeKey = resume_key;
1963         pSMB->SearchFlags =
1964             cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1965         /* BB add check to make sure we do not cross end of smb */
1966         if(name_len < CIFS_MAX_MSGSIZE) {
1967                 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1968                 byte_count += name_len;
1969         }
1970         params += name_len;
1971         byte_count = params + 1 /* pad */ ;
1972         pSMB->TotalParameterCount = cpu_to_le16(params);
1973         pSMB->ParameterCount = pSMB->TotalParameterCount;
1974         /* BB improve error handling here */
1975         pSMB->hdr.smb_buf_length += byte_count;
1976         pSMB->ByteCount = cpu_to_le16(byte_count);
1977
1978         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1979                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1980
1981         if (rc) {
1982                 if (rc == -EBADF)
1983                         rc = 0; /* search probably was closed at end of search above */
1984                 else
1985                         cFYI(1, ("FindNext returned = %d", rc));
1986         } else {                /* decode response */
1987                 /* BB add safety checks for these memcpys */
1988                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1989                         *pUnicodeFlag = TRUE;
1990                 else
1991                         *pUnicodeFlag = FALSE;
1992                 memcpy(findParms,
1993                        (char *) &pSMBr->hdr.Protocol +
1994                        le16_to_cpu(pSMBr->ParameterOffset),
1995                        sizeof (T2_FNEXT_RSP_PARMS));
1996                 response_data =
1997                     (char *) &pSMBr->hdr.Protocol +
1998                     le16_to_cpu(pSMBr->DataOffset);
1999                 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
2000         }
2001         if (pSMB)
2002                 cifs_buf_release(pSMB);
2003
2004         /* Note: On -EAGAIN error only caller can retry on handle based calls
2005                 since file handle passed in no longer valid */
2006
2007         return rc;
2008 }
2009
2010 int
2011 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2012 {
2013         int rc = 0;
2014         FINDCLOSE_REQ *pSMB = NULL;
2015         CLOSE_RSP *pSMBr = NULL;
2016         int bytes_returned;
2017
2018         cFYI(1, ("In CIFSSMBFindClose"));
2019         rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
2020                       (void **) &pSMBr);
2021         /* no sense returning error if session restarted
2022                 file handle has been closed */
2023         if(rc == -EAGAIN)
2024                 return 0;
2025         if (rc)
2026                 return rc;
2027
2028         pSMB->FileID = searchHandle;
2029         pSMB->ByteCount = 0;
2030         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2031                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2032         if (rc) {
2033                 cERROR(1, ("Send error in FindClose = %d", rc));
2034         }
2035         if (pSMB)
2036                 cifs_buf_release(pSMB);
2037
2038         /* Since session is dead, search handle closed on server already */
2039         if (rc == -EAGAIN)
2040                 rc = 0;
2041
2042         return rc;
2043 }
2044
2045 int
2046 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2047                 const unsigned char *searchName,
2048                 unsigned char **targetUNCs,
2049                 unsigned int *number_of_UNC_in_array,
2050                 const struct nls_table *nls_codepage)
2051 {
2052 /* TRANS2_GET_DFS_REFERRAL */
2053         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2054         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2055         struct dfs_referral_level_3 * referrals = NULL;
2056         int rc = 0;
2057         int bytes_returned;
2058         int name_len;
2059         unsigned int i;
2060         char * temp;
2061         __u16 params, byte_count;
2062         *number_of_UNC_in_array = 0;
2063         *targetUNCs = NULL;
2064
2065         cFYI(1, ("In GetDFSRefer the path %s", searchName));
2066         if (ses == NULL)
2067                 return -ENODEV;
2068 getDFSRetry:
2069         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2070                       (void **) &pSMBr);
2071         if (rc)
2072                 return rc;
2073
2074         pSMB->hdr.Tid = ses->ipc_tid;
2075         pSMB->hdr.Uid = ses->Suid;
2076         if (ses->capabilities & CAP_STATUS32) {
2077                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2078         }
2079         if (ses->capabilities & CAP_DFS) {
2080                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2081         }
2082
2083         if (ses->capabilities & CAP_UNICODE) {
2084                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2085                 name_len =
2086                     cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2087                                   searchName, 530
2088                                   /* find define for this maxpathcomponent */
2089                                   , nls_codepage);
2090                 name_len++;     /* trailing null */
2091                 name_len *= 2;
2092         } else {                /* BB improve the check for buffer overruns BB */
2093                 name_len = strnlen(searchName, 530);
2094                 name_len++;     /* trailing null */
2095                 strncpy(pSMB->RequestFileName, searchName, name_len);
2096         }
2097
2098         params = 2 /* level */  + name_len /*includes null */ ;
2099         pSMB->TotalDataCount = 0;
2100         pSMB->DataCount = 0;
2101         pSMB->DataOffset = 0;
2102         pSMB->MaxParameterCount = 0;
2103         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2104         pSMB->MaxSetupCount = 0;
2105         pSMB->Reserved = 0;
2106         pSMB->Flags = 0;
2107         pSMB->Timeout = 0;
2108         pSMB->Reserved2 = 0;
2109         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2110         struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2111         pSMB->SetupCount = 1;
2112         pSMB->Reserved3 = 0;
2113         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2114         byte_count = params + 3 /* pad */ ;
2115         pSMB->ParameterCount = cpu_to_le16(params);
2116         pSMB->TotalParameterCount = pSMB->ParameterCount;
2117         pSMB->MaxReferralLevel = cpu_to_le16(3);
2118         pSMB->hdr.smb_buf_length += byte_count;
2119         pSMB->ByteCount = cpu_to_le16(byte_count);
2120
2121         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2122                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2123         if (rc) {
2124                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2125         } else {                /* decode response */
2126 /* BB Add logic to parse referrals here */
2127                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2128                 __u16 data_count = le16_to_cpu(pSMBr->DataCount);
2129                 cFYI(1,
2130                      ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
2131                       pSMBr->ByteCount, data_offset));
2132                 if ((pSMBr->ByteCount < 17) || (data_offset > 512))     /* BB also check enough total bytes returned */
2133                         rc = -EIO;      /* bad smb */
2134                 else {
2135                         referrals = 
2136                             (struct dfs_referral_level_3 *) 
2137                                         (8 /* sizeof start of data block */ +
2138                                         data_offset +
2139                                         (char *) &pSMBr->hdr.Protocol); 
2140                         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",
2141                                 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)));
2142                         /* BB This field is actually two bytes in from start of
2143                            data block so we could do safety check that DataBlock
2144                            begins at address of pSMBr->NumberOfReferrals */
2145                         *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2146
2147                         /* BB Fix below so can return more than one referral */
2148                         if(*number_of_UNC_in_array > 1)
2149                                 *number_of_UNC_in_array = 1;
2150
2151                         /* get the length of the strings describing refs */
2152                         name_len = 0;
2153                         for(i=0;i<*number_of_UNC_in_array;i++) {
2154                                 /* make sure that DfsPathOffset not past end */
2155                                 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2156                                 if (offset > data_count) {
2157                                         /* if invalid referral, stop here and do 
2158                                         not try to copy any more */
2159                                         *number_of_UNC_in_array = i;
2160                                         break;
2161                                 } 
2162                                 temp = ((char *)referrals) + offset;
2163
2164                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2165                                         name_len += UniStrnlen((wchar_t *)temp,data_count);
2166                                 } else {
2167                                         name_len += strnlen(temp,data_count);
2168                                 }
2169                                 referrals++;
2170                                 /* BB add check that referral pointer does not fall off end PDU */
2171                                 
2172                         }
2173                         /* BB add check for name_len bigger than bcc */
2174                         *targetUNCs = 
2175                                 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2176                         if(*targetUNCs == NULL) {
2177                                 rc = -ENOMEM;
2178                                 goto GetDFSRefExit;
2179                         }
2180                         /* copy the ref strings */
2181                         referrals =  
2182                             (struct dfs_referral_level_3 *) 
2183                                         (8 /* sizeof data hdr */ +
2184                                         data_offset + 
2185                                         (char *) &pSMBr->hdr.Protocol);
2186
2187                         for(i=0;i<*number_of_UNC_in_array;i++) {
2188                                 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2189                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2190                                         cifs_strfromUCS_le(*targetUNCs,
2191                                                 (wchar_t *) temp, name_len, nls_codepage);
2192                                 } else {
2193                                         strncpy(*targetUNCs,temp,name_len);
2194                                 }
2195                                 /*  BB update target_uncs pointers */
2196                                 referrals++;
2197                         }
2198                         temp = *targetUNCs;
2199                         temp[name_len] = 0;
2200                 }
2201
2202         }
2203 GetDFSRefExit:
2204         if (pSMB)
2205                 cifs_buf_release(pSMB);
2206
2207         if (rc == -EAGAIN)
2208                 goto getDFSRetry;
2209
2210         return rc;
2211 }
2212
2213 int
2214 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2215                struct kstatfs *FSData, const struct nls_table *nls_codepage)
2216 {
2217 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2218         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2219         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2220         FILE_SYSTEM_INFO *response_data;
2221         int rc = 0;
2222         int bytes_returned = 0;
2223         __u16 params, byte_count;
2224
2225         cFYI(1, ("In QFSInfo"));
2226 QFSInfoRetry:
2227         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2228                       (void **) &pSMBr);
2229         if (rc)
2230                 return rc;
2231
2232         params = 2;     /* level */
2233         pSMB->TotalDataCount = 0;
2234         pSMB->MaxParameterCount = cpu_to_le16(2);
2235         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2236         pSMB->MaxSetupCount = 0;
2237         pSMB->Reserved = 0;
2238         pSMB->Flags = 0;
2239         pSMB->Timeout = 0;
2240         pSMB->Reserved2 = 0;
2241         byte_count = params + 1 /* pad */ ;
2242         pSMB->TotalParameterCount = cpu_to_le16(params);
2243         pSMB->ParameterCount = pSMB->TotalParameterCount;
2244         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2245         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2246         pSMB->DataCount = 0;
2247         pSMB->DataOffset = 0;
2248         pSMB->SetupCount = 1;
2249         pSMB->Reserved3 = 0;
2250         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2251         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2252         pSMB->hdr.smb_buf_length += byte_count;
2253         pSMB->ByteCount = cpu_to_le16(byte_count);
2254
2255         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2256                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2257         if (rc) {
2258                 cERROR(1, ("Send error in QFSInfo = %d", rc));
2259         } else {                /* decode response */
2260                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2261                 cFYI(1,
2262                      ("Decoding qfsinfo response.  BCC: %d  Offset %d",
2263                       pSMBr->ByteCount, data_offset));
2264                 if ((pSMBr->ByteCount < 24) || (data_offset > 512))     /* BB also check enough total bytes returned */
2265                         rc = -EIO;      /* bad smb */
2266                 else {
2267                         response_data =
2268                             (FILE_SYSTEM_INFO
2269                              *) (((char *) &pSMBr->hdr.Protocol) +
2270                                  data_offset);
2271                         FSData->f_bsize =
2272                             le32_to_cpu(response_data->BytesPerSector) *
2273                             le32_to_cpu(response_data->
2274                                         SectorsPerAllocationUnit);
2275                         FSData->f_blocks =
2276                             le64_to_cpu(response_data->TotalAllocationUnits);
2277                         FSData->f_bfree = FSData->f_bavail =
2278                             le64_to_cpu(response_data->FreeAllocationUnits);
2279                         cFYI(1,
2280                              ("Blocks: %lld  Free: %lld Block size %ld",
2281                               (unsigned long long)FSData->f_blocks,
2282                               (unsigned long long)FSData->f_bfree,
2283                               FSData->f_bsize));
2284                 }
2285         }
2286         if (pSMB)
2287                 cifs_buf_release(pSMB);
2288
2289         if (rc == -EAGAIN)
2290                 goto QFSInfoRetry;
2291
2292         return rc;
2293 }
2294
2295 int
2296 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
2297                         const struct nls_table *nls_codepage)
2298 {
2299 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
2300         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2301         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2302         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2303         int rc = 0;
2304         int bytes_returned = 0;
2305         __u16 params, byte_count;
2306
2307         cFYI(1, ("In QFSAttributeInfo"));
2308 QFSAttributeRetry:
2309         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2310                       (void **) &pSMBr);
2311         if (rc)
2312                 return rc;
2313
2314         params = 2;     /* level */
2315         pSMB->TotalDataCount = 0;
2316         pSMB->MaxParameterCount = cpu_to_le16(2);
2317         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2318         pSMB->MaxSetupCount = 0;
2319         pSMB->Reserved = 0;
2320         pSMB->Flags = 0;
2321         pSMB->Timeout = 0;
2322         pSMB->Reserved2 = 0;
2323         byte_count = params + 1 /* pad */ ;
2324         pSMB->TotalParameterCount = cpu_to_le16(params);
2325         pSMB->ParameterCount = pSMB->TotalParameterCount;
2326         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2327         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2328         pSMB->DataCount = 0;
2329         pSMB->DataOffset = 0;
2330         pSMB->SetupCount = 1;
2331         pSMB->Reserved3 = 0;
2332         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2333         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2334         pSMB->hdr.smb_buf_length += byte_count;
2335         pSMB->ByteCount = cpu_to_le16(byte_count);
2336
2337         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2338                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2339         if (rc) {
2340                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
2341         } else {                /* decode response */
2342                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2343                 if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {   /* BB also check enough bytes returned */
2344                         rc = -EIO;      /* bad smb */
2345                 } else {
2346                         response_data =
2347                             (FILE_SYSTEM_ATTRIBUTE_INFO
2348                              *) (((char *) &pSMBr->hdr.Protocol) +
2349                                  data_offset);
2350                         memcpy(&tcon->fsAttrInfo, response_data,
2351                                sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
2352                 }
2353         }
2354         if (pSMB)
2355                 cifs_buf_release(pSMB);
2356
2357         if (rc == -EAGAIN)
2358                 goto QFSAttributeRetry;
2359
2360         return rc;
2361 }
2362
2363 int
2364 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
2365                      const struct nls_table *nls_codepage)
2366 {
2367 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
2368         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2369         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2370         FILE_SYSTEM_DEVICE_INFO *response_data;
2371         int rc = 0;
2372         int bytes_returned = 0;
2373         __u16 params, byte_count;
2374
2375         cFYI(1, ("In QFSDeviceInfo"));
2376 QFSDeviceRetry:
2377         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2378                       (void **) &pSMBr);
2379         if (rc)
2380                 return rc;
2381
2382         params = 2;     /* level */
2383         pSMB->TotalDataCount = 0;
2384         pSMB->MaxParameterCount = cpu_to_le16(2);
2385         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2386         pSMB->MaxSetupCount = 0;
2387         pSMB->Reserved = 0;
2388         pSMB->Flags = 0;
2389         pSMB->Timeout = 0;
2390         pSMB->Reserved2 = 0;
2391         byte_count = params + 1 /* pad */ ;
2392         pSMB->TotalParameterCount = cpu_to_le16(params);
2393         pSMB->ParameterCount = pSMB->TotalParameterCount;
2394         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2395         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2396
2397         pSMB->DataCount = 0;
2398         pSMB->DataOffset = 0;
2399         pSMB->SetupCount = 1;
2400         pSMB->Reserved3 = 0;
2401         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2402         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
2403         pSMB->hdr.smb_buf_length += byte_count;
2404         pSMB->ByteCount = cpu_to_le16(byte_count);
2405
2406         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2407                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2408         if (rc) {
2409                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
2410         } else {                /* decode response */
2411                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2412                 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
2413                  || (data_offset > 512))
2414                         rc = -EIO;      /* bad smb */
2415                 else {
2416                         response_data =
2417                             (FILE_SYSTEM_DEVICE_INFO
2418                              *) (((char *) &pSMBr->hdr.Protocol) +
2419                                  data_offset);
2420                         memcpy(&tcon->fsDevInfo, response_data,
2421                                sizeof (FILE_SYSTEM_DEVICE_INFO));
2422                 }
2423         }
2424         if (pSMB)
2425                 cifs_buf_release(pSMB);
2426
2427         if (rc == -EAGAIN)
2428                 goto QFSDeviceRetry;
2429
2430         return rc;
2431 }
2432
2433 int
2434 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
2435                    const struct nls_table *nls_codepage)
2436 {
2437 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
2438         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2439         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2440         FILE_SYSTEM_UNIX_INFO *response_data;
2441         int rc = 0;
2442         int bytes_returned = 0;
2443         __u16 params, byte_count;
2444
2445         cFYI(1, ("In QFSUnixInfo"));
2446 QFSUnixRetry:
2447         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2448                       (void **) &pSMBr);
2449         if (rc)
2450                 return rc;
2451
2452         params = 2;     /* level */
2453         pSMB->TotalDataCount = 0;
2454         pSMB->DataCount = 0;
2455         pSMB->DataOffset = 0;
2456         pSMB->MaxParameterCount = cpu_to_le16(2);
2457         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
2458         pSMB->MaxSetupCount = 0;
2459         pSMB->Reserved = 0;
2460         pSMB->Flags = 0;
2461         pSMB->Timeout = 0;
2462         pSMB->Reserved2 = 0;
2463         byte_count = params + 1 /* pad */ ;
2464         pSMB->ParameterCount = cpu_to_le16(params);
2465         pSMB->TotalParameterCount = pSMB->ParameterCount;
2466         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
2467         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2468         pSMB->SetupCount = 1;
2469         pSMB->Reserved3 = 0;
2470         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2471         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2472         pSMB->hdr.smb_buf_length += byte_count;
2473         pSMB->ByteCount = cpu_to_le16(byte_count);
2474
2475         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2476                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2477         if (rc) {
2478                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2479         } else {                /* decode response */
2480                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
2481                 if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {
2482                         rc = -EIO;      /* bad smb */
2483                 } else {
2484                         response_data =
2485                             (FILE_SYSTEM_UNIX_INFO
2486                              *) (((char *) &pSMBr->hdr.Protocol) +
2487                                  data_offset);
2488                         memcpy(&tcon->fsUnixInfo, response_data,
2489                                sizeof (FILE_SYSTEM_UNIX_INFO));
2490                 }
2491         }
2492         if (pSMB)
2493                 cifs_buf_release(pSMB);
2494
2495         if (rc == -EAGAIN)
2496                 goto QFSUnixRetry;
2497
2498
2499         return rc;
2500 }
2501
2502 /* We can not use write of zero bytes trick to 
2503    set file size due to need for large file support.  Also note that 
2504    this SetPathInfo is preferred to SetFileInfo based method in next 
2505    routine which is only needed to work around a sharing violation bug
2506    in Samba which this routine can run into */
2507
2508 int
2509 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
2510               __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2511 {
2512         struct smb_com_transaction2_spi_req *pSMB = NULL;
2513         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2514         struct file_end_of_file_info *parm_data;
2515         int name_len;
2516         int rc = 0;
2517         int bytes_returned = 0;
2518         __u16 params, byte_count, data_count, param_offset, offset;
2519
2520         cFYI(1, ("In SetEOF"));
2521 SetEOFRetry:
2522         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2523                       (void **) &pSMBr);
2524         if (rc)
2525                 return rc;
2526
2527         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2528                 name_len =
2529                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2530                                   /* find define for this maxpathcomponent */
2531                                   , nls_codepage);
2532                 name_len++;     /* trailing null */
2533                 name_len *= 2;
2534         } else {                /* BB improve the check for buffer overruns BB */
2535                 name_len = strnlen(fileName, 530);
2536                 name_len++;     /* trailing null */
2537                 strncpy(pSMB->FileName, fileName, name_len);
2538         }
2539         params = 6 + name_len;
2540         data_count = sizeof (struct file_end_of_file_info);
2541         pSMB->MaxParameterCount = cpu_to_le16(2);
2542         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2543         pSMB->MaxSetupCount = 0;
2544         pSMB->Reserved = 0;
2545         pSMB->Flags = 0;
2546         pSMB->Timeout = 0;
2547         pSMB->Reserved2 = 0;
2548         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2549                                      InformationLevel) - 4;
2550         offset = param_offset + params;
2551         if(SetAllocation) {
2552                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2553                     pSMB->InformationLevel =
2554                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2555                 else
2556                     pSMB->InformationLevel =
2557                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2558         } else /* Set File Size */  {    
2559             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2560                     pSMB->InformationLevel =
2561                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2562             else
2563                     pSMB->InformationLevel =
2564                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2565         }
2566
2567         parm_data =
2568             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2569                                        offset);
2570         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2571         pSMB->DataOffset = cpu_to_le16(offset);
2572         pSMB->SetupCount = 1;
2573         pSMB->Reserved3 = 0;
2574         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2575         byte_count = 3 /* pad */  + params + data_count;
2576         pSMB->DataCount = cpu_to_le16(data_count);
2577         pSMB->TotalDataCount = pSMB->DataCount;
2578         pSMB->ParameterCount = cpu_to_le16(params);
2579         pSMB->TotalParameterCount = pSMB->ParameterCount;
2580         pSMB->Reserved4 = 0;
2581         pSMB->hdr.smb_buf_length += byte_count;
2582         parm_data->FileSize = cpu_to_le64(size);
2583         pSMB->ByteCount = cpu_to_le16(byte_count);
2584         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2585                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2586         if (rc) {
2587                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2588         }
2589
2590         if (pSMB)
2591                 cifs_buf_release(pSMB);
2592
2593         if (rc == -EAGAIN)
2594                 goto SetEOFRetry;
2595
2596         return rc;
2597 }
2598
2599 int
2600 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, 
2601                    __u16 fid, __u32 pid_of_opener, int SetAllocation)
2602 {
2603         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2604         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2605         char *data_offset;
2606         struct file_end_of_file_info *parm_data;
2607         int rc = 0;
2608         int bytes_returned = 0;
2609         __u16 params, param_offset, offset, byte_count, count;
2610
2611         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
2612                         (long long)size));
2613         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2614                       (void **) &pSMBr);
2615         if (rc)
2616                 return rc;
2617
2618         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
2619         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
2620     
2621         params = 6;
2622         pSMB->MaxSetupCount = 0;
2623         pSMB->Reserved = 0;
2624         pSMB->Flags = 0;
2625         pSMB->Timeout = 0;
2626         pSMB->Reserved2 = 0;
2627         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2628         offset = param_offset + params;
2629
2630         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;  
2631
2632         count = sizeof(struct file_end_of_file_info);
2633         pSMB->MaxParameterCount = cpu_to_le16(2);
2634         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2635         pSMB->SetupCount = 1;
2636         pSMB->Reserved3 = 0;
2637         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2638         byte_count = 3 /* pad */  + params + count;
2639         pSMB->DataCount = cpu_to_le16(count);
2640         pSMB->ParameterCount = cpu_to_le16(params);
2641         pSMB->TotalDataCount = pSMB->DataCount;
2642         pSMB->TotalParameterCount = pSMB->ParameterCount;
2643         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2644         parm_data =
2645                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2646                         offset);
2647         pSMB->DataOffset = cpu_to_le16(offset);
2648         parm_data->FileSize = cpu_to_le64(size);
2649         pSMB->Fid = fid;
2650         if(SetAllocation) {
2651                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2652                         pSMB->InformationLevel =
2653                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2654                 else
2655                         pSMB->InformationLevel =
2656                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2657         } else /* Set File Size */  {    
2658             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2659                     pSMB->InformationLevel =
2660                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2661             else
2662                     pSMB->InformationLevel =
2663                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2664         }
2665         pSMB->Reserved4 = 0;
2666         pSMB->hdr.smb_buf_length += byte_count;
2667         pSMB->ByteCount = cpu_to_le16(byte_count);
2668         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2669                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2670         if (rc) {
2671                 cFYI(1,
2672                      ("Send error in SetFileInfo (SetFileSize) = %d",
2673                       rc));
2674         }
2675
2676         if (pSMB)
2677                 cifs_buf_release(pSMB);
2678
2679         /* Note: On -EAGAIN error only caller can retry on handle based calls 
2680                 since file handle passed in no longer valid */
2681
2682         return rc;
2683 }
2684
2685 int
2686 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
2687                 const FILE_BASIC_INFO * data, 
2688                 const struct nls_table *nls_codepage)
2689 {
2690         TRANSACTION2_SPI_REQ *pSMB = NULL;
2691         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2692         int name_len;
2693         int rc = 0;
2694         int bytes_returned = 0;
2695         char *data_offset;
2696         __u16 params, param_offset, offset, byte_count, count;
2697
2698         cFYI(1, ("In SetTimes"));
2699
2700 SetTimesRetry:
2701         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2702                       (void **) &pSMBr);
2703         if (rc)
2704                 return rc;
2705
2706         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2707                 name_len =
2708                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2709                                   /* find define for this maxpathcomponent */
2710                                   , nls_codepage);
2711                 name_len++;     /* trailing null */
2712                 name_len *= 2;
2713         } else {                /* BB improve the check for buffer overruns BB */
2714                 name_len = strnlen(fileName, 530);
2715                 name_len++;     /* trailing null */
2716                 strncpy(pSMB->FileName, fileName, name_len);
2717         }
2718
2719         params = 6 + name_len;
2720         count = sizeof (FILE_BASIC_INFO);
2721         pSMB->MaxParameterCount = cpu_to_le16(2);
2722         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2723         pSMB->MaxSetupCount = 0;
2724         pSMB->Reserved = 0;
2725         pSMB->Flags = 0;
2726         pSMB->Timeout = 0;
2727         pSMB->Reserved2 = 0;
2728         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2729                                      InformationLevel) - 4;
2730         offset = param_offset + params;
2731         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2732         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2733         pSMB->DataOffset = cpu_to_le16(offset);
2734         pSMB->SetupCount = 1;
2735         pSMB->Reserved3 = 0;
2736         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2737         byte_count = 3 /* pad */  + params + count;
2738
2739         pSMB->DataCount = cpu_to_le16(count);
2740         pSMB->ParameterCount = cpu_to_le16(params);
2741         pSMB->TotalDataCount = pSMB->DataCount;
2742         pSMB->TotalParameterCount = pSMB->ParameterCount;
2743         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2744                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2745         else
2746                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2747         pSMB->Reserved4 = 0;
2748         pSMB->hdr.smb_buf_length += byte_count;
2749         memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2750         pSMB->ByteCount = cpu_to_le16(byte_count);
2751         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2752                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2753         if (rc) {
2754                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2755         }
2756
2757         if (pSMB)
2758                 cifs_buf_release(pSMB);
2759
2760         if (rc == -EAGAIN)
2761                 goto SetTimesRetry;
2762
2763         return rc;
2764 }
2765
2766 int
2767 CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
2768                 FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
2769 {
2770         TRANSACTION2_SPI_REQ *pSMB = NULL;
2771         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2772         int name_len;
2773         int rc = 0;
2774         int bytes_returned = 0;
2775         char *data_offset;
2776         __u16 params, param_offset, count, offset, byte_count;
2777
2778         cFYI(1, ("In SetTimesLegacy"));
2779
2780 SetTimesRetryLegacy:
2781         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2782                       (void **) &pSMBr);
2783         if (rc)
2784                 return rc;
2785
2786         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2787                 name_len =
2788                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2789                                   /* find define for this maxpathcomponent */
2790                                   , nls_codepage);
2791                 name_len++;     /* trailing null */
2792                 name_len *= 2;
2793         } else {                /* BB improve the check for buffer overruns BB */
2794                 name_len = strnlen(fileName, 530);
2795                 name_len++;     /* trailing null */
2796                 strncpy(pSMB->FileName, fileName, name_len);
2797         }
2798 /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
2799         in parent function, from the better and ususal FILE_BASIC_INFO */
2800         params = 6 + name_len;
2801         count = sizeof (FILE_INFO_STANDARD);
2802         pSMB->MaxParameterCount = cpu_to_le16(2);
2803         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2804         pSMB->MaxSetupCount = 0;
2805         pSMB->Reserved = 0;
2806         pSMB->Flags = 0;
2807         pSMB->Timeout = 0;
2808         pSMB->Reserved2 = 0;
2809         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2810                                      InformationLevel) - 4;
2811         offset = param_offset + params;
2812         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2813         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2814         pSMB->DataOffset = cpu_to_le16(offset);
2815         pSMB->SetupCount = 1;
2816         pSMB->Reserved3 = 0;
2817         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2818         byte_count = 3 /* pad */  + params + count;
2819
2820         pSMB->DataCount = cpu_to_le16(count);
2821         pSMB->ParameterCount = cpu_to_le16(params);
2822         pSMB->TotalDataCount = pSMB->DataCount;
2823         pSMB->TotalParameterCount = pSMB->ParameterCount;
2824         /* I doubt that passthrough levels apply to this old
2825         preNT info level */
2826 /*      if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2827                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2828         else*/
2829                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
2830         pSMB->Reserved4 = 0;
2831         pSMB->hdr.smb_buf_length += byte_count;
2832         memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
2833         pSMB->ByteCount = cpu_to_le16(byte_count);
2834         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2835                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2836         if (rc) {
2837                 cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
2838         }
2839
2840         if (pSMB)
2841                 cifs_buf_release(pSMB);
2842
2843         if (rc == -EAGAIN)
2844                 goto SetTimesRetryLegacy;
2845
2846         return rc;
2847 }
2848
2849 int
2850 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2851                     char *fileName, __u64 mode, __u64 uid, __u64 gid,
2852                     dev_t device, const struct nls_table *nls_codepage)
2853 {
2854         TRANSACTION2_SPI_REQ *pSMB = NULL;
2855         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2856         int name_len;
2857         int rc = 0;
2858         int bytes_returned = 0;
2859         FILE_UNIX_BASIC_INFO *data_offset;
2860         __u16 params, param_offset, offset, count, byte_count;
2861
2862         cFYI(1, ("In SetUID/GID/Mode"));
2863 setPermsRetry:
2864         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2865                       (void **) &pSMBr);
2866         if (rc)
2867                 return rc;
2868
2869         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2870                 name_len =
2871                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2872                                   /* find define for this maxpathcomponent */
2873                                   , nls_codepage);
2874                 name_len++;     /* trailing null */
2875                 name_len *= 2;
2876         } else {                /* BB improve the check for buffer overruns BB */
2877                 name_len = strnlen(fileName, 530);
2878                 name_len++;     /* trailing null */
2879                 strncpy(pSMB->FileName, fileName, name_len);
2880         }
2881
2882         params = 6 + name_len;
2883         count = sizeof (FILE_UNIX_BASIC_INFO);
2884         pSMB->MaxParameterCount = cpu_to_le16(2);
2885         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2886         pSMB->MaxSetupCount = 0;
2887         pSMB->Reserved = 0;
2888         pSMB->Flags = 0;
2889         pSMB->Timeout = 0;
2890         pSMB->Reserved2 = 0;
2891         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2892                                      InformationLevel) - 4;
2893         offset = param_offset + params;
2894         data_offset =
2895             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2896                                       offset);
2897         pSMB->DataOffset = cpu_to_le16(offset);
2898         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2899         pSMB->SetupCount = 1;
2900         pSMB->Reserved3 = 0;
2901         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2902         byte_count = 3 /* pad */  + params + count;
2903         pSMB->ParameterCount = cpu_to_le16(params);
2904         pSMB->DataCount = cpu_to_le16(count);
2905         pSMB->TotalParameterCount = pSMB->ParameterCount;
2906         pSMB->TotalDataCount = pSMB->DataCount;
2907         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2908         pSMB->Reserved4 = 0;
2909         pSMB->hdr.smb_buf_length += byte_count;
2910         data_offset->Uid = cpu_to_le64(uid);
2911         data_offset->Gid = cpu_to_le64(gid);
2912         /* better to leave device as zero when it is  */
2913         data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2914         data_offset->DevMinor = cpu_to_le64(MINOR(device));
2915         data_offset->Permissions = cpu_to_le64(mode);
2916     
2917         if(S_ISREG(mode))
2918                 data_offset->Type = cpu_to_le32(UNIX_FILE);
2919         else if(S_ISDIR(mode))
2920                 data_offset->Type = cpu_to_le32(UNIX_DIR);
2921         else if(S_ISLNK(mode))
2922                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
2923         else if(S_ISCHR(mode))
2924                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
2925         else if(S_ISBLK(mode))
2926                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
2927         else if(S_ISFIFO(mode))
2928                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
2929         else if(S_ISSOCK(mode))
2930                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
2931
2932
2933         pSMB->ByteCount = cpu_to_le16(byte_count);
2934         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2935                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2936         if (rc) {
2937                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2938         }
2939
2940         if (pSMB)
2941                 cifs_buf_release(pSMB);
2942         if (rc == -EAGAIN)
2943                 goto setPermsRetry;
2944         return rc;
2945 }
2946
2947 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
2948                         const int notify_subdirs, const __u16 netfid,
2949                         __u32 filter, const struct nls_table *nls_codepage)
2950 {
2951         int rc = 0;
2952         struct smb_com_transaction_change_notify_req * pSMB = NULL;
2953         struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
2954         int bytes_returned;
2955
2956         cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
2957         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2958                       (void **) &pSMBr);
2959         if (rc)
2960                 return rc;
2961
2962         pSMB->TotalParameterCount = 0 ;
2963         pSMB->TotalDataCount = 0;
2964         pSMB->MaxParameterCount = cpu_to_le32(2);
2965         /* BB find exact data count max from sess structure BB */
2966         pSMB->MaxDataCount = 0; /* same in little endian or be */
2967         pSMB->MaxSetupCount = 4;
2968         pSMB->Reserved = 0;
2969         pSMB->ParameterOffset = 0;
2970         pSMB->DataCount = 0;
2971         pSMB->DataOffset = 0;
2972         pSMB->SetupCount = 4; /* single byte does not need le conversion */
2973         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
2974         pSMB->ParameterCount = pSMB->TotalParameterCount;
2975         if(notify_subdirs)
2976                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
2977         pSMB->Reserved2 = 0;
2978         pSMB->CompletionFilter = cpu_to_le32(filter);
2979         pSMB->Fid = netfid; /* file handle always le */
2980         pSMB->ByteCount = 0;
2981
2982         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2983                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2984         if (rc) {
2985                 cFYI(1, ("Error in Notify = %d", rc));
2986         }
2987         if (pSMB)
2988                 cifs_buf_release(pSMB);
2989 /*              if (rc == -EAGAIN)
2990                         goto NotifyRetry; */
2991         return rc;      
2992 }
2993 #ifdef CONFIG_CIFS_XATTR
2994 ssize_t
2995 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
2996                  const unsigned char *searchName,
2997                  char * EAData, size_t buf_size,
2998                  const struct nls_table *nls_codepage)
2999 {
3000                 /* BB assumes one setup word */
3001         TRANSACTION2_QPI_REQ *pSMB = NULL;
3002         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3003         int rc = 0;
3004         int bytes_returned;
3005         int name_len;
3006         struct fea * temp_fea;
3007         char * temp_ptr;
3008         __u16 params, byte_count;
3009
3010         cFYI(1, ("In Query All EAs path %s", searchName));
3011 QAllEAsRetry:
3012         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3013                       (void **) &pSMBr);
3014         if (rc)
3015                 return rc;
3016
3017         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3018                 name_len =
3019                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
3020                                   /* find define for this maxpathcomponent */
3021                                   , nls_codepage);
3022                 name_len++;     /* trailing null */
3023                 name_len *= 2;
3024         } else {        /* BB improve the check for buffer overruns BB */
3025                 name_len = strnlen(searchName, 530);
3026                 name_len++;     /* trailing null */
3027                 strncpy(pSMB->FileName, searchName, name_len);
3028         }
3029
3030         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3031         pSMB->TotalDataCount = 0;
3032         pSMB->MaxParameterCount = cpu_to_le16(2);
3033         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3034         pSMB->MaxSetupCount = 0;
3035         pSMB->Reserved = 0;
3036         pSMB->Flags = 0;
3037         pSMB->Timeout = 0;
3038         pSMB->Reserved2 = 0;
3039         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3040         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3041         pSMB->DataCount = 0;
3042         pSMB->DataOffset = 0;
3043         pSMB->SetupCount = 1;
3044         pSMB->Reserved3 = 0;
3045         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3046         byte_count = params + 1 /* pad */ ;
3047         pSMB->TotalParameterCount = cpu_to_le16(params);
3048         pSMB->ParameterCount = pSMB->TotalParameterCount;
3049         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3050         pSMB->Reserved4 = 0;
3051         pSMB->hdr.smb_buf_length += byte_count;
3052         pSMB->ByteCount = cpu_to_le16(byte_count);
3053
3054         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3055                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3056         if (rc) {
3057                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3058         } else {                /* decode response */
3059                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
3060                 /* BB also check enough total bytes returned */
3061                 /* BB we need to improve the validity checking
3062                 of these trans2 responses */
3063                 if ((pSMBr->ByteCount < 4) || (data_offset > 512)) 
3064                         rc = -EIO;      /* bad smb */
3065            /* else if (pFindData){
3066                         memcpy((char *) pFindData,
3067                                (char *) &pSMBr->hdr.Protocol +
3068                                data_offset, kl);
3069                 }*/ else {
3070                         /* check that length of list is not more than bcc */
3071                         /* check that each entry does not go beyond length
3072                            of list */
3073                         /* check that each element of each entry does not
3074                            go beyond end of list */
3075                         struct fealist * ea_response_data;
3076                         rc = 0;
3077                         /* validate_trans2_offsets() */
3078                         /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3079                         ea_response_data = (struct fealist *)
3080                                 (((char *) &pSMBr->hdr.Protocol) +
3081                                 data_offset);
3082                         name_len = le32_to_cpu(ea_response_data->list_len);
3083                         cFYI(1,("ea length %d", name_len));
3084                         if(name_len <= 8) {
3085                         /* returned EA size zeroed at top of function */
3086                                 cFYI(1,("empty EA list returned from server"));
3087                         } else {
3088                                 /* account for ea list len */
3089                                 name_len -= 4;
3090                                 temp_fea = ea_response_data->list;
3091                                 temp_ptr = (char *)temp_fea;
3092                                 while(name_len > 0) {
3093                                         __u16 value_len;
3094                                         name_len -= 4;
3095                                         temp_ptr += 4;
3096                                         rc += temp_fea->name_len;
3097                                 /* account for prefix user. and trailing null */
3098                                         rc = rc + 5 + 1; 
3099                                         if(rc<(int)buf_size) {
3100                                                 memcpy(EAData,"user.",5);
3101                                                 EAData+=5;
3102                                                 memcpy(EAData,temp_ptr,temp_fea->name_len);
3103                                                 EAData+=temp_fea->name_len;
3104                                                 /* null terminate name */
3105                                                 *EAData = 0;
3106                                                 EAData = EAData + 1;
3107                                         } else if(buf_size == 0) {
3108                                                 /* skip copy - calc size only */
3109                                         } else {
3110                                                 /* stop before overrun buffer */
3111                                                 rc = -ERANGE;
3112                                                 break;
3113                                         }
3114                                         name_len -= temp_fea->name_len;
3115                                         temp_ptr += temp_fea->name_len;
3116                                         /* account for trailing null */
3117                                         name_len--;
3118                                         temp_ptr++;
3119                                         value_len = le16_to_cpu(temp_fea->value_len);
3120                                         name_len -= value_len;
3121                                         temp_ptr += value_len;
3122                                         /* BB check that temp_ptr is still within smb BB*/
3123                                 /* no trailing null to account for in value len */
3124                                         /* go on to next EA */
3125                                         temp_fea = (struct fea *)temp_ptr;
3126                                 }
3127                         }
3128                 }
3129         }
3130         if (pSMB)
3131                 cifs_buf_release(pSMB);
3132         if (rc == -EAGAIN)
3133                 goto QAllEAsRetry;
3134
3135         return (ssize_t)rc;
3136 }
3137
3138 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3139                 const unsigned char * searchName,const unsigned char * ea_name,
3140                 unsigned char * ea_value, size_t buf_size, 
3141                 const struct nls_table *nls_codepage)
3142 {
3143         TRANSACTION2_QPI_REQ *pSMB = NULL;
3144         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3145         int rc = 0;
3146         int bytes_returned;
3147         int name_len;
3148         struct fea * temp_fea;
3149         char * temp_ptr;
3150         __u16 params, byte_count;
3151
3152         cFYI(1, ("In Query EA path %s", searchName));
3153 QEARetry:
3154         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3155                       (void **) &pSMBr);
3156         if (rc)
3157                 return rc;
3158
3159         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3160                 name_len =
3161                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
3162                                   /* find define for this maxpathcomponent */
3163                                   , nls_codepage);
3164                 name_len++;     /* trailing null */
3165                 name_len *= 2;
3166         } else {        /* BB improve the check for buffer overruns BB */
3167                 name_len = strnlen(searchName, 530);
3168                 name_len++;     /* trailing null */
3169                 strncpy(pSMB->FileName, searchName, name_len);
3170         }
3171
3172         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3173         pSMB->TotalDataCount = 0;
3174         pSMB->MaxParameterCount = cpu_to_le16(2);
3175         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3176         pSMB->MaxSetupCount = 0;
3177         pSMB->Reserved = 0;
3178         pSMB->Flags = 0;
3179         pSMB->Timeout = 0;
3180         pSMB->Reserved2 = 0;
3181         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3182         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3183         pSMB->DataCount = 0;
3184         pSMB->DataOffset = 0;
3185         pSMB->SetupCount = 1;
3186         pSMB->Reserved3 = 0;
3187         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3188         byte_count = params + 1 /* pad */ ;
3189         pSMB->TotalParameterCount = cpu_to_le16(params);
3190         pSMB->ParameterCount = pSMB->TotalParameterCount;
3191         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3192         pSMB->Reserved4 = 0;
3193         pSMB->hdr.smb_buf_length += byte_count;
3194         pSMB->ByteCount = cpu_to_le16(byte_count);
3195
3196         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3197                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3198         if (rc) {
3199                 cFYI(1, ("Send error in Query EA = %d", rc));
3200         } else {                /* decode response */
3201                 __u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
3202                 /* BB also check enough total bytes returned */
3203                 /* BB we need to improve the validity checking
3204                 of these trans2 responses */
3205                 if ((pSMBr->ByteCount < 4) || (data_offset > 512)) 
3206                         rc = -EIO;      /* bad smb */
3207            /* else if (pFindData){
3208                         memcpy((char *) pFindData,
3209                                (char *) &pSMBr->hdr.Protocol +
3210                                data_offset, kl);
3211                 }*/ else {
3212                         /* check that length of list is not more than bcc */
3213                         /* check that each entry does not go beyond length
3214                            of list */
3215                         /* check that each element of each entry does not
3216                            go beyond end of list */
3217                         struct fealist * ea_response_data;
3218                         rc = -ENOENT;
3219                         /* validate_trans2_offsets() */
3220                         /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3221                         ea_response_data = (struct fealist *)
3222                                 (((char *) &pSMBr->hdr.Protocol) +
3223                                 data_offset);
3224                         name_len = le32_to_cpu(ea_response_data->list_len);
3225                         cFYI(1,("ea length %d", name_len));
3226                         if(name_len <= 8) {
3227                         /* returned EA size zeroed at top of function */
3228                                 cFYI(1,("empty EA list returned from server"));
3229                         } else {
3230                                 /* account for ea list len */
3231                                 name_len -= 4;
3232                                 temp_fea = ea_response_data->list;
3233                                 temp_ptr = (char *)temp_fea;
3234                                 /* loop through checking if we have a matching
3235                                 name and then return the associated value */
3236                                 while(name_len > 0) {
3237                                         __u16 value_len;
3238                                         name_len -= 4;
3239                                         temp_ptr += 4;
3240                                         value_len = le16_to_cpu(temp_fea->value_len);
3241                                 /* BB validate that value_len falls within SMB, 
3242                                 even though maximum for name_len is 255 */ 
3243                                         if(memcmp(temp_fea->name,ea_name,
3244                                                   temp_fea->name_len) == 0) {
3245                                                 /* found a match */
3246                                                 rc = value_len;
3247                                 /* account for prefix user. and trailing null */
3248                                                 if(rc<=(int)buf_size) {
3249                                                         memcpy(ea_value,
3250                                                                 temp_fea->name+temp_fea->name_len+1,
3251                                                                 rc);
3252                                                         /* ea values, unlike ea names,
3253                                                         are not null terminated */
3254                                                 } else if(buf_size == 0) {
3255                                                 /* skip copy - calc size only */
3256                                                 } else {
3257                                                         /* stop before overrun buffer */
3258                                                         rc = -ERANGE;
3259                                                 }
3260                                                 break;
3261                                         }
3262                                         name_len -= temp_fea->name_len;
3263                                         temp_ptr += temp_fea->name_len;
3264                                         /* account for trailing null */
3265                                         name_len--;
3266                                         temp_ptr++;
3267                                         name_len -= value_len;
3268                                         temp_ptr += value_len;
3269                                 /* no trailing null to account for in value len */
3270                                         /* go on to next EA */
3271                                         temp_fea = (struct fea *)temp_ptr;
3272                                 }
3273                         } 
3274                 }
3275         }
3276         if (pSMB)
3277                 cifs_buf_release(pSMB);
3278         if (rc == -EAGAIN)
3279                 goto QEARetry;
3280
3281         return (ssize_t)rc;
3282 }
3283
3284 int
3285 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3286                 const char * ea_name, const void * ea_value, 
3287                 const __u16 ea_value_len, const struct nls_table *nls_codepage)
3288 {
3289         struct smb_com_transaction2_spi_req *pSMB = NULL;
3290         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3291         struct fealist *parm_data;
3292         int name_len;
3293         int rc = 0;
3294         int bytes_returned = 0;
3295         __u16 params, param_offset, byte_count, offset, count;
3296
3297         cFYI(1, ("In SetEA"));
3298 SetEARetry:
3299         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3300                       (void **) &pSMBr);
3301         if (rc)
3302                 return rc;
3303
3304         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3305                 name_len =
3306                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
3307                                   /* find define for this maxpathcomponent */
3308                                   , nls_codepage);
3309                 name_len++;     /* trailing null */
3310                 name_len *= 2;
3311         } else {                /* BB improve the check for buffer overruns BB */
3312                 name_len = strnlen(fileName, 530);
3313                 name_len++;     /* trailing null */
3314                 strncpy(pSMB->FileName, fileName, name_len);
3315         }
3316
3317         params = 6 + name_len;
3318
3319         /* done calculating parms using name_len of file name,
3320         now use name_len to calculate length of ea name
3321         we are going to create in the inode xattrs */
3322         if(ea_name == NULL)
3323                 name_len = 0;
3324         else
3325                 name_len = strnlen(ea_name,255);
3326
3327         count = sizeof(*parm_data) + ea_value_len + name_len + 1;
3328         pSMB->MaxParameterCount = cpu_to_le16(2);
3329         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3330         pSMB->MaxSetupCount = 0;
3331         pSMB->Reserved = 0;
3332         pSMB->Flags = 0;
3333         pSMB->Timeout = 0;
3334         pSMB->Reserved2 = 0;
3335         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3336                                      InformationLevel) - 4;
3337         offset = param_offset + params;
3338         pSMB->InformationLevel =
3339                 cpu_to_le16(SMB_SET_FILE_EA);
3340
3341         parm_data =
3342                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
3343                                        offset);
3344         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3345         pSMB->DataOffset = cpu_to_le16(offset);
3346         pSMB->SetupCount = 1;
3347         pSMB->Reserved3 = 0;
3348         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3349         byte_count = 3 /* pad */  + params + count;
3350         pSMB->DataCount = cpu_to_le16(count);
3351         parm_data->list_len = cpu_to_le32(count);
3352         parm_data->list[0].EA_flags = 0;
3353         /* we checked above that name len is less than 255 */
3354         parm_data->list[0].name_len = (__u8)name_len;;
3355         /* EA names are always ASCII */
3356         strncpy(parm_data->list[0].name,ea_name,name_len);
3357         parm_data->list[0].name[name_len] = 0;
3358         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
3359         /* caller ensures that ea_value_len is less than 64K but
3360         we need to ensure that it fits within the smb */
3361
3362         /*BB add length check that it would fit in negotiated SMB buffer size BB */
3363         /* if(ea_value_len > buffer_size - 512 (enough for header)) */
3364         if(ea_value_len)
3365                 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
3366
3367         pSMB->TotalDataCount = pSMB->DataCount;
3368         pSMB->ParameterCount = cpu_to_le16(params);
3369         pSMB->TotalParameterCount = pSMB->ParameterCount;
3370         pSMB->Reserved4 = 0;
3371         pSMB->hdr.smb_buf_length += byte_count;
3372         pSMB->ByteCount = cpu_to_le16(byte_count);
3373         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3374                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3375         if (rc) {
3376                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
3377         }
3378
3379         if (pSMB)
3380                 cifs_buf_release(pSMB);
3381
3382         if (rc == -EAGAIN)
3383                 goto SetEARetry;
3384
3385         return rc;
3386 }
3387
3388 #endif