]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - fs/cifs/cifssmb.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-2.6.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2009
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 differently for reconnection purposes since we never     */
28  /* want to reuse a stale file handle and only the caller knows the file info */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
35 #include "cifspdu.h"
36 #include "cifsglob.h"
37 #include "cifsacl.h"
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
41
42 #ifdef CONFIG_CIFS_POSIX
43 static struct {
44         int index;
45         char *name;
46 } protocols[] = {
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48         {LANMAN_PROT, "\2LM1.2X002"},
49         {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51         {CIFS_PROT, "\2NT LM 0.12"},
52         {POSIX_PROT, "\2POSIX 2"},
53         {BAD_PROT, "\2"}
54 };
55 #else
56 static struct {
57         int index;
58         char *name;
59 } protocols[] = {
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61         {LANMAN_PROT, "\2LM1.2X002"},
62         {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64         {CIFS_PROT, "\2NT LM 0.12"},
65         {BAD_PROT, "\2"}
66 };
67 #endif
68
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
73 #else
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
76 #else /* not posix */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
79 #else
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
83
84 /* Mark as invalid, all open files on tree connections since they
85    were closed when session to server was lost */
86 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
87 {
88         struct cifsFileInfo *open_file = NULL;
89         struct list_head *tmp;
90         struct list_head *tmp1;
91
92 /* list all files open on tree connection and mark them invalid */
93         write_lock(&GlobalSMBSeslock);
94         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
95                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
96                 open_file->invalidHandle = true;
97                 open_file->oplock_break_cancelled = true;
98         }
99         write_unlock(&GlobalSMBSeslock);
100         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
101            to this tcon */
102 }
103
104 /* reconnect the socket, tcon, and smb session if needed */
105 static int
106 cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
107 {
108         int rc = 0;
109         struct cifsSesInfo *ses;
110         struct TCP_Server_Info *server;
111         struct nls_table *nls_codepage;
112
113         /*
114          * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
115          * tcp and smb session status done differently for those three - in the
116          * calling routine
117          */
118         if (!tcon)
119                 return 0;
120
121         ses = tcon->ses;
122         server = ses->server;
123
124         /*
125          * only tree disconnect, open, and write, (and ulogoff which does not
126          * have tcon) are allowed as we start force umount
127          */
128         if (tcon->tidStatus == CifsExiting) {
129                 if (smb_command != SMB_COM_WRITE_ANDX &&
130                     smb_command != SMB_COM_OPEN_ANDX &&
131                     smb_command != SMB_COM_TREE_DISCONNECT) {
132                         cFYI(1, ("can not send cmd %d while umounting",
133                                 smb_command));
134                         return -ENODEV;
135                 }
136         }
137
138         if (ses->status == CifsExiting)
139                 return -EIO;
140
141         /*
142          * Give demultiplex thread up to 10 seconds to reconnect, should be
143          * greater than cifs socket timeout which is 7 seconds
144          */
145         while (server->tcpStatus == CifsNeedReconnect) {
146                 wait_event_interruptible_timeout(server->response_q,
147                         (server->tcpStatus == CifsGood), 10 * HZ);
148
149                 /* is TCP session is reestablished now ?*/
150                 if (server->tcpStatus != CifsNeedReconnect)
151                         break;
152
153                 /*
154                  * on "soft" mounts we wait once. Hard mounts keep
155                  * retrying until process is killed or server comes
156                  * back on-line
157                  */
158                 if (!tcon->retry || ses->status == CifsExiting) {
159                         cFYI(1, ("gave up waiting on reconnect in smb_init"));
160                         return -EHOSTDOWN;
161                 }
162         }
163
164         if (!ses->need_reconnect && !tcon->need_reconnect)
165                 return 0;
166
167         nls_codepage = load_nls_default();
168
169         /*
170          * need to prevent multiple threads trying to simultaneously
171          * reconnect the same SMB session
172          */
173         mutex_lock(&ses->session_mutex);
174         if (ses->need_reconnect)
175                 rc = cifs_setup_session(0, ses, nls_codepage);
176
177         /* do we need to reconnect tcon? */
178         if (rc || !tcon->need_reconnect) {
179                 mutex_unlock(&ses->session_mutex);
180                 goto out;
181         }
182
183         mark_open_files_invalid(tcon);
184         rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
185         mutex_unlock(&ses->session_mutex);
186         cFYI(1, ("reconnect tcon rc = %d", rc));
187
188         if (rc)
189                 goto out;
190
191         /*
192          * FIXME: check if wsize needs updated due to negotiated smb buffer
193          *        size shrinking
194          */
195         atomic_inc(&tconInfoReconnectCount);
196
197         /* tell server Unix caps we support */
198         if (ses->capabilities & CAP_UNIX)
199                 reset_cifs_unix_caps(0, tcon, NULL, NULL);
200
201         /*
202          * Removed call to reopen open files here. It is safer (and faster) to
203          * reopen files one at a time as needed in read and write.
204          *
205          * FIXME: what about file locks? don't we need to reclaim them ASAP?
206          */
207
208 out:
209         /*
210          * Check if handle based operation so we know whether we can continue
211          * or not without returning to caller to reset file handle
212          */
213         switch (smb_command) {
214         case SMB_COM_READ_ANDX:
215         case SMB_COM_WRITE_ANDX:
216         case SMB_COM_CLOSE:
217         case SMB_COM_FIND_CLOSE2:
218         case SMB_COM_LOCKING_ANDX:
219                 rc = -EAGAIN;
220         }
221
222         unload_nls(nls_codepage);
223         return rc;
224 }
225
226 /* Allocate and return pointer to an SMB request buffer, and set basic
227    SMB information in the SMB header.  If the return code is zero, this
228    function must have filled in request_buf pointer */
229 static int
230 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
231                 void **request_buf)
232 {
233         int rc = 0;
234
235         rc = cifs_reconnect_tcon(tcon, smb_command);
236         if (rc)
237                 return rc;
238
239         *request_buf = cifs_small_buf_get();
240         if (*request_buf == NULL) {
241                 /* BB should we add a retry in here if not a writepage? */
242                 return -ENOMEM;
243         }
244
245         header_assemble((struct smb_hdr *) *request_buf, smb_command,
246                         tcon, wct);
247
248         if (tcon != NULL)
249                 cifs_stats_inc(&tcon->num_smbs_sent);
250
251         return rc;
252 }
253
254 int
255 small_smb_init_no_tc(const int smb_command, const int wct,
256                      struct cifsSesInfo *ses, void **request_buf)
257 {
258         int rc;
259         struct smb_hdr *buffer;
260
261         rc = small_smb_init(smb_command, wct, NULL, request_buf);
262         if (rc)
263                 return rc;
264
265         buffer = (struct smb_hdr *)*request_buf;
266         buffer->Mid = GetNextMid(ses->server);
267         if (ses->capabilities & CAP_UNICODE)
268                 buffer->Flags2 |= SMBFLG2_UNICODE;
269         if (ses->capabilities & CAP_STATUS32)
270                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
271
272         /* uid, tid can stay at zero as set in header assemble */
273
274         /* BB add support for turning on the signing when
275         this function is used after 1st of session setup requests */
276
277         return rc;
278 }
279
280 /* If the return code is zero, this function must fill in request_buf pointer */
281 static int
282 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
283          void **request_buf /* returned */ ,
284          void **response_buf /* returned */ )
285 {
286         int rc = 0;
287
288         rc = cifs_reconnect_tcon(tcon, smb_command);
289         if (rc)
290                 return rc;
291
292         *request_buf = cifs_buf_get();
293         if (*request_buf == NULL) {
294                 /* BB should we add a retry in here if not a writepage? */
295                 return -ENOMEM;
296         }
297     /* Although the original thought was we needed the response buf for  */
298     /* potential retries of smb operations it turns out we can determine */
299     /* from the mid flags when the request buffer can be resent without  */
300     /* having to use a second distinct buffer for the response */
301         if (response_buf)
302                 *response_buf = *request_buf;
303
304         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
305                         wct);
306
307         if (tcon != NULL)
308                 cifs_stats_inc(&tcon->num_smbs_sent);
309
310         return rc;
311 }
312
313 static int validate_t2(struct smb_t2_rsp *pSMB)
314 {
315         int rc = -EINVAL;
316         int total_size;
317         char *pBCC;
318
319         /* check for plausible wct, bcc and t2 data and parm sizes */
320         /* check for parm and data offset going beyond end of smb */
321         if (pSMB->hdr.WordCount >= 10) {
322                 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
323                    (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
324                         /* check that bcc is at least as big as parms + data */
325                         /* check that bcc is less than negotiated smb buffer */
326                         total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
327                         if (total_size < 512) {
328                                 total_size +=
329                                         le16_to_cpu(pSMB->t2_rsp.DataCount);
330                                 /* BCC le converted in SendReceive */
331                                 pBCC = (pSMB->hdr.WordCount * 2) +
332                                         sizeof(struct smb_hdr) +
333                                         (char *)pSMB;
334                                 if ((total_size <= (*(u16 *)pBCC)) &&
335                                    (total_size <
336                                         CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
337                                         return 0;
338                                 }
339                         }
340                 }
341         }
342         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
343                 sizeof(struct smb_t2_rsp) + 16);
344         return rc;
345 }
346 int
347 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
348 {
349         NEGOTIATE_REQ *pSMB;
350         NEGOTIATE_RSP *pSMBr;
351         int rc = 0;
352         int bytes_returned;
353         int i;
354         struct TCP_Server_Info *server;
355         u16 count;
356         unsigned int secFlags;
357         u16 dialect;
358
359         if (ses->server)
360                 server = ses->server;
361         else {
362                 rc = -EIO;
363                 return rc;
364         }
365         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
366                       (void **) &pSMB, (void **) &pSMBr);
367         if (rc)
368                 return rc;
369
370         /* if any of auth flags (ie not sign or seal) are overriden use them */
371         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
372                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
373         else /* if override flags set only sign/seal OR them with global auth */
374                 secFlags = extended_security | ses->overrideSecFlg;
375
376         cFYI(1, ("secFlags 0x%x", secFlags));
377
378         pSMB->hdr.Mid = GetNextMid(server);
379         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
380
381         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
382                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
383         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
384                 cFYI(1, ("Kerberos only mechanism, enable extended security"));
385                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
386         }
387 #ifdef CONFIG_CIFS_EXPERIMENTAL
388         else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
389                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
390         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
391                 cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
392                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
393         }
394 #endif
395
396         count = 0;
397         for (i = 0; i < CIFS_NUM_PROT; i++) {
398                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
399                 count += strlen(protocols[i].name) + 1;
400                 /* null at end of source and target buffers anyway */
401         }
402         pSMB->hdr.smb_buf_length += count;
403         pSMB->ByteCount = cpu_to_le16(count);
404
405         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
406                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
407         if (rc != 0)
408                 goto neg_err_exit;
409
410         dialect = le16_to_cpu(pSMBr->DialectIndex);
411         cFYI(1, ("Dialect: %d", dialect));
412         /* Check wct = 1 error case */
413         if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
414                 /* core returns wct = 1, but we do not ask for core - otherwise
415                 small wct just comes when dialect index is -1 indicating we
416                 could not negotiate a common dialect */
417                 rc = -EOPNOTSUPP;
418                 goto neg_err_exit;
419 #ifdef CONFIG_CIFS_WEAK_PW_HASH
420         } else if ((pSMBr->hdr.WordCount == 13)
421                         && ((dialect == LANMAN_PROT)
422                                 || (dialect == LANMAN2_PROT))) {
423                 __s16 tmp;
424                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
425
426                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
427                         (secFlags & CIFSSEC_MAY_PLNTXT))
428                         server->secType = LANMAN;
429                 else {
430                         cERROR(1, ("mount failed weak security disabled"
431                                    " in /proc/fs/cifs/SecurityFlags"));
432                         rc = -EOPNOTSUPP;
433                         goto neg_err_exit;
434                 }
435                 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
436                 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
437                 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
438                                 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
439                 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
440                 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
441                 /* even though we do not use raw we might as well set this
442                 accurately, in case we ever find a need for it */
443                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
444                         server->max_rw = 0xFF00;
445                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
446                 } else {
447                         server->max_rw = 0;/* do not need to use raw anyway */
448                         server->capabilities = CAP_MPX_MODE;
449                 }
450                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
451                 if (tmp == -1) {
452                         /* OS/2 often does not set timezone therefore
453                          * we must use server time to calc time zone.
454                          * Could deviate slightly from the right zone.
455                          * Smallest defined timezone difference is 15 minutes
456                          * (i.e. Nepal).  Rounding up/down is done to match
457                          * this requirement.
458                          */
459                         int val, seconds, remain, result;
460                         struct timespec ts, utc;
461                         utc = CURRENT_TIME;
462                         ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
463                                             rsp->SrvTime.Time, 0);
464                         cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
465                                 (int)ts.tv_sec, (int)utc.tv_sec,
466                                 (int)(utc.tv_sec - ts.tv_sec)));
467                         val = (int)(utc.tv_sec - ts.tv_sec);
468                         seconds = abs(val);
469                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
470                         remain = seconds % MIN_TZ_ADJ;
471                         if (remain >= (MIN_TZ_ADJ / 2))
472                                 result += MIN_TZ_ADJ;
473                         if (val < 0)
474                                 result = -result;
475                         server->timeAdj = result;
476                 } else {
477                         server->timeAdj = (int)tmp;
478                         server->timeAdj *= 60; /* also in seconds */
479                 }
480                 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
481
482
483                 /* BB get server time for time conversions and add
484                 code to use it and timezone since this is not UTC */
485
486                 if (rsp->EncryptionKeyLength ==
487                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
488                         memcpy(server->cryptKey, rsp->EncryptionKey,
489                                 CIFS_CRYPTO_KEY_SIZE);
490                 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
491                         rc = -EIO; /* need cryptkey unless plain text */
492                         goto neg_err_exit;
493                 }
494
495                 cFYI(1, ("LANMAN negotiated"));
496                 /* we will not end up setting signing flags - as no signing
497                 was in LANMAN and server did not return the flags on */
498                 goto signing_check;
499 #else /* weak security disabled */
500         } else if (pSMBr->hdr.WordCount == 13) {
501                 cERROR(1, ("mount failed, cifs module not built "
502                           "with CIFS_WEAK_PW_HASH support"));
503                 rc = -EOPNOTSUPP;
504 #endif /* WEAK_PW_HASH */
505                 goto neg_err_exit;
506         } else if (pSMBr->hdr.WordCount != 17) {
507                 /* unknown wct */
508                 rc = -EOPNOTSUPP;
509                 goto neg_err_exit;
510         }
511         /* else wct == 17 NTLM */
512         server->secMode = pSMBr->SecurityMode;
513         if ((server->secMode & SECMODE_USER) == 0)
514                 cFYI(1, ("share mode security"));
515
516         if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
517 #ifdef CONFIG_CIFS_WEAK_PW_HASH
518                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
519 #endif /* CIFS_WEAK_PW_HASH */
520                         cERROR(1, ("Server requests plain text password"
521                                   " but client support disabled"));
522
523         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
524                 server->secType = NTLMv2;
525         else if (secFlags & CIFSSEC_MAY_NTLM)
526                 server->secType = NTLM;
527         else if (secFlags & CIFSSEC_MAY_NTLMV2)
528                 server->secType = NTLMv2;
529         else if (secFlags & CIFSSEC_MAY_KRB5)
530                 server->secType = Kerberos;
531         else if (secFlags & CIFSSEC_MAY_NTLMSSP)
532                 server->secType = RawNTLMSSP;
533         else if (secFlags & CIFSSEC_MAY_LANMAN)
534                 server->secType = LANMAN;
535 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
536         else if (secFlags & CIFSSEC_MAY_PLNTXT)
537                 server->secType = ??
538 #endif */
539         else {
540                 rc = -EOPNOTSUPP;
541                 cERROR(1, ("Invalid security type"));
542                 goto neg_err_exit;
543         }
544         /* else ... any others ...? */
545
546         /* one byte, so no need to convert this or EncryptionKeyLen from
547            little endian */
548         server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
549         /* probably no need to store and check maxvcs */
550         server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
551                         (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
552         server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
553         cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
554         GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
555         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
556         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
557         server->timeAdj *= 60;
558         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
559                 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
560                        CIFS_CRYPTO_KEY_SIZE);
561         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
562                         && (pSMBr->EncryptionKeyLength == 0)) {
563                 /* decode security blob */
564         } else if (server->secMode & SECMODE_PW_ENCRYPT) {
565                 rc = -EIO; /* no crypt key only if plain text pwd */
566                 goto neg_err_exit;
567         }
568
569         /* BB might be helpful to save off the domain of server here */
570
571         if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
572                 (server->capabilities & CAP_EXTENDED_SECURITY)) {
573                 count = pSMBr->ByteCount;
574                 if (count < 16) {
575                         rc = -EIO;
576                         goto neg_err_exit;
577                 }
578                 read_lock(&cifs_tcp_ses_lock);
579                 if (server->srv_count > 1) {
580                         read_unlock(&cifs_tcp_ses_lock);
581                         if (memcmp(server->server_GUID,
582                                    pSMBr->u.extended_response.
583                                    GUID, 16) != 0) {
584                                 cFYI(1, ("server UID changed"));
585                                 memcpy(server->server_GUID,
586                                         pSMBr->u.extended_response.GUID,
587                                         16);
588                         }
589                 } else {
590                         read_unlock(&cifs_tcp_ses_lock);
591                         memcpy(server->server_GUID,
592                                pSMBr->u.extended_response.GUID, 16);
593                 }
594
595                 if (count == 16) {
596                         server->secType = RawNTLMSSP;
597                 } else {
598                         rc = decode_negTokenInit(pSMBr->u.extended_response.
599                                                  SecurityBlob,
600                                                  count - 16,
601                                                  &server->secType);
602                         if (rc == 1)
603                                 rc = 0;
604                         else
605                                 rc = -EINVAL;
606                 }
607         } else
608                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
609
610 #ifdef CONFIG_CIFS_WEAK_PW_HASH
611 signing_check:
612 #endif
613         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
614                 /* MUST_SIGN already includes the MAY_SIGN FLAG
615                    so if this is zero it means that signing is disabled */
616                 cFYI(1, ("Signing disabled"));
617                 if (server->secMode & SECMODE_SIGN_REQUIRED) {
618                         cERROR(1, ("Server requires "
619                                    "packet signing to be enabled in "
620                                    "/proc/fs/cifs/SecurityFlags."));
621                         rc = -EOPNOTSUPP;
622                 }
623                 server->secMode &=
624                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
625         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
626                 /* signing required */
627                 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
628                 if ((server->secMode &
629                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
630                         cERROR(1,
631                                 ("signing required but server lacks support"));
632                         rc = -EOPNOTSUPP;
633                 } else
634                         server->secMode |= SECMODE_SIGN_REQUIRED;
635         } else {
636                 /* signing optional ie CIFSSEC_MAY_SIGN */
637                 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
638                         server->secMode &=
639                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
640         }
641
642 neg_err_exit:
643         cifs_buf_release(pSMB);
644
645         cFYI(1, ("negprot rc %d", rc));
646         return rc;
647 }
648
649 int
650 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
651 {
652         struct smb_hdr *smb_buffer;
653         int rc = 0;
654
655         cFYI(1, ("In tree disconnect"));
656
657         /* BB: do we need to check this? These should never be NULL. */
658         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
659                 return -EIO;
660
661         /*
662          * No need to return error on this operation if tid invalidated and
663          * closed on server already e.g. due to tcp session crashing. Also,
664          * the tcon is no longer on the list, so no need to take lock before
665          * checking this.
666          */
667         if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
668                 return 0;
669
670         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
671                             (void **)&smb_buffer);
672         if (rc)
673                 return rc;
674
675         rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
676         if (rc)
677                 cFYI(1, ("Tree disconnect failed %d", rc));
678
679         /* No need to return error on this operation if tid invalidated and
680            closed on server already e.g. due to tcp session crashing */
681         if (rc == -EAGAIN)
682                 rc = 0;
683
684         return rc;
685 }
686
687 int
688 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
689 {
690         LOGOFF_ANDX_REQ *pSMB;
691         int rc = 0;
692
693         cFYI(1, ("In SMBLogoff for session disconnect"));
694
695         /*
696          * BB: do we need to check validity of ses and server? They should
697          * always be valid since we have an active reference. If not, that
698          * should probably be a BUG()
699          */
700         if (!ses || !ses->server)
701                 return -EIO;
702
703         mutex_lock(&ses->session_mutex);
704         if (ses->need_reconnect)
705                 goto session_already_dead; /* no need to send SMBlogoff if uid
706                                               already closed due to reconnect */
707         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
708         if (rc) {
709                 mutex_unlock(&ses->session_mutex);
710                 return rc;
711         }
712
713         pSMB->hdr.Mid = GetNextMid(ses->server);
714
715         if (ses->server->secMode &
716                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
717                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
718
719         pSMB->hdr.Uid = ses->Suid;
720
721         pSMB->AndXCommand = 0xFF;
722         rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
723 session_already_dead:
724         mutex_unlock(&ses->session_mutex);
725
726         /* if session dead then we do not need to do ulogoff,
727                 since server closed smb session, no sense reporting
728                 error */
729         if (rc == -EAGAIN)
730                 rc = 0;
731         return rc;
732 }
733
734 int
735 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
736                  __u16 type, const struct nls_table *nls_codepage, int remap)
737 {
738         TRANSACTION2_SPI_REQ *pSMB = NULL;
739         TRANSACTION2_SPI_RSP *pSMBr = NULL;
740         struct unlink_psx_rq *pRqD;
741         int name_len;
742         int rc = 0;
743         int bytes_returned = 0;
744         __u16 params, param_offset, offset, byte_count;
745
746         cFYI(1, ("In POSIX delete"));
747 PsxDelete:
748         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
749                       (void **) &pSMBr);
750         if (rc)
751                 return rc;
752
753         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
754                 name_len =
755                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
756                                      PATH_MAX, nls_codepage, remap);
757                 name_len++;     /* trailing null */
758                 name_len *= 2;
759         } else { /* BB add path length overrun check */
760                 name_len = strnlen(fileName, PATH_MAX);
761                 name_len++;     /* trailing null */
762                 strncpy(pSMB->FileName, fileName, name_len);
763         }
764
765         params = 6 + name_len;
766         pSMB->MaxParameterCount = cpu_to_le16(2);
767         pSMB->MaxDataCount = 0; /* BB double check this with jra */
768         pSMB->MaxSetupCount = 0;
769         pSMB->Reserved = 0;
770         pSMB->Flags = 0;
771         pSMB->Timeout = 0;
772         pSMB->Reserved2 = 0;
773         param_offset = offsetof(struct smb_com_transaction2_spi_req,
774                                 InformationLevel) - 4;
775         offset = param_offset + params;
776
777         /* Setup pointer to Request Data (inode type) */
778         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
779         pRqD->type = cpu_to_le16(type);
780         pSMB->ParameterOffset = cpu_to_le16(param_offset);
781         pSMB->DataOffset = cpu_to_le16(offset);
782         pSMB->SetupCount = 1;
783         pSMB->Reserved3 = 0;
784         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
785         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
786
787         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
788         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
789         pSMB->ParameterCount = cpu_to_le16(params);
790         pSMB->TotalParameterCount = pSMB->ParameterCount;
791         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
792         pSMB->Reserved4 = 0;
793         pSMB->hdr.smb_buf_length += byte_count;
794         pSMB->ByteCount = cpu_to_le16(byte_count);
795         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
796                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
797         if (rc)
798                 cFYI(1, ("Posix delete returned %d", rc));
799         cifs_buf_release(pSMB);
800
801         cifs_stats_inc(&tcon->num_deletes);
802
803         if (rc == -EAGAIN)
804                 goto PsxDelete;
805
806         return rc;
807 }
808
809 int
810 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
811                const struct nls_table *nls_codepage, int remap)
812 {
813         DELETE_FILE_REQ *pSMB = NULL;
814         DELETE_FILE_RSP *pSMBr = NULL;
815         int rc = 0;
816         int bytes_returned;
817         int name_len;
818
819 DelFileRetry:
820         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
821                       (void **) &pSMBr);
822         if (rc)
823                 return rc;
824
825         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
826                 name_len =
827                     cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
828                                      PATH_MAX, nls_codepage, remap);
829                 name_len++;     /* trailing null */
830                 name_len *= 2;
831         } else {                /* BB improve check for buffer overruns BB */
832                 name_len = strnlen(fileName, PATH_MAX);
833                 name_len++;     /* trailing null */
834                 strncpy(pSMB->fileName, fileName, name_len);
835         }
836         pSMB->SearchAttributes =
837             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
838         pSMB->BufferFormat = 0x04;
839         pSMB->hdr.smb_buf_length += name_len + 1;
840         pSMB->ByteCount = cpu_to_le16(name_len + 1);
841         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
842                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
843         cifs_stats_inc(&tcon->num_deletes);
844         if (rc)
845                 cFYI(1, ("Error in RMFile = %d", rc));
846
847         cifs_buf_release(pSMB);
848         if (rc == -EAGAIN)
849                 goto DelFileRetry;
850
851         return rc;
852 }
853
854 int
855 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
856              const struct nls_table *nls_codepage, int remap)
857 {
858         DELETE_DIRECTORY_REQ *pSMB = NULL;
859         DELETE_DIRECTORY_RSP *pSMBr = NULL;
860         int rc = 0;
861         int bytes_returned;
862         int name_len;
863
864         cFYI(1, ("In CIFSSMBRmDir"));
865 RmDirRetry:
866         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
867                       (void **) &pSMBr);
868         if (rc)
869                 return rc;
870
871         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
872                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
873                                          PATH_MAX, nls_codepage, remap);
874                 name_len++;     /* trailing null */
875                 name_len *= 2;
876         } else {                /* BB improve check for buffer overruns BB */
877                 name_len = strnlen(dirName, PATH_MAX);
878                 name_len++;     /* trailing null */
879                 strncpy(pSMB->DirName, dirName, name_len);
880         }
881
882         pSMB->BufferFormat = 0x04;
883         pSMB->hdr.smb_buf_length += name_len + 1;
884         pSMB->ByteCount = cpu_to_le16(name_len + 1);
885         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
886                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887         cifs_stats_inc(&tcon->num_rmdirs);
888         if (rc)
889                 cFYI(1, ("Error in RMDir = %d", rc));
890
891         cifs_buf_release(pSMB);
892         if (rc == -EAGAIN)
893                 goto RmDirRetry;
894         return rc;
895 }
896
897 int
898 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
899              const char *name, const struct nls_table *nls_codepage, int remap)
900 {
901         int rc = 0;
902         CREATE_DIRECTORY_REQ *pSMB = NULL;
903         CREATE_DIRECTORY_RSP *pSMBr = NULL;
904         int bytes_returned;
905         int name_len;
906
907         cFYI(1, ("In CIFSSMBMkDir"));
908 MkDirRetry:
909         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
910                       (void **) &pSMBr);
911         if (rc)
912                 return rc;
913
914         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
915                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
916                                             PATH_MAX, nls_codepage, remap);
917                 name_len++;     /* trailing null */
918                 name_len *= 2;
919         } else {                /* BB improve check for buffer overruns BB */
920                 name_len = strnlen(name, PATH_MAX);
921                 name_len++;     /* trailing null */
922                 strncpy(pSMB->DirName, name, name_len);
923         }
924
925         pSMB->BufferFormat = 0x04;
926         pSMB->hdr.smb_buf_length += name_len + 1;
927         pSMB->ByteCount = cpu_to_le16(name_len + 1);
928         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
929                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
930         cifs_stats_inc(&tcon->num_mkdirs);
931         if (rc)
932                 cFYI(1, ("Error in Mkdir = %d", rc));
933
934         cifs_buf_release(pSMB);
935         if (rc == -EAGAIN)
936                 goto MkDirRetry;
937         return rc;
938 }
939
940 int
941 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
942                 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
943                 __u32 *pOplock, const char *name,
944                 const struct nls_table *nls_codepage, int remap)
945 {
946         TRANSACTION2_SPI_REQ *pSMB = NULL;
947         TRANSACTION2_SPI_RSP *pSMBr = NULL;
948         int name_len;
949         int rc = 0;
950         int bytes_returned = 0;
951         __u16 params, param_offset, offset, byte_count, count;
952         OPEN_PSX_REQ *pdata;
953         OPEN_PSX_RSP *psx_rsp;
954
955         cFYI(1, ("In POSIX Create"));
956 PsxCreat:
957         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
958                       (void **) &pSMBr);
959         if (rc)
960                 return rc;
961
962         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
963                 name_len =
964                     cifsConvertToUCS((__le16 *) pSMB->FileName, name,
965                                      PATH_MAX, nls_codepage, remap);
966                 name_len++;     /* trailing null */
967                 name_len *= 2;
968         } else {        /* BB improve the check for buffer overruns BB */
969                 name_len = strnlen(name, PATH_MAX);
970                 name_len++;     /* trailing null */
971                 strncpy(pSMB->FileName, name, name_len);
972         }
973
974         params = 6 + name_len;
975         count = sizeof(OPEN_PSX_REQ);
976         pSMB->MaxParameterCount = cpu_to_le16(2);
977         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
978         pSMB->MaxSetupCount = 0;
979         pSMB->Reserved = 0;
980         pSMB->Flags = 0;
981         pSMB->Timeout = 0;
982         pSMB->Reserved2 = 0;
983         param_offset = offsetof(struct smb_com_transaction2_spi_req,
984                                 InformationLevel) - 4;
985         offset = param_offset + params;
986         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
987         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
988         pdata->Permissions = cpu_to_le64(mode);
989         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
990         pdata->OpenFlags =  cpu_to_le32(*pOplock);
991         pSMB->ParameterOffset = cpu_to_le16(param_offset);
992         pSMB->DataOffset = cpu_to_le16(offset);
993         pSMB->SetupCount = 1;
994         pSMB->Reserved3 = 0;
995         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
996         byte_count = 3 /* pad */  + params + count;
997
998         pSMB->DataCount = cpu_to_le16(count);
999         pSMB->ParameterCount = cpu_to_le16(params);
1000         pSMB->TotalDataCount = pSMB->DataCount;
1001         pSMB->TotalParameterCount = pSMB->ParameterCount;
1002         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1003         pSMB->Reserved4 = 0;
1004         pSMB->hdr.smb_buf_length += byte_count;
1005         pSMB->ByteCount = cpu_to_le16(byte_count);
1006         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1007                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1008         if (rc) {
1009                 cFYI(1, ("Posix create returned %d", rc));
1010                 goto psx_create_err;
1011         }
1012
1013         cFYI(1, ("copying inode info"));
1014         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1015
1016         if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1017                 rc = -EIO;      /* bad smb */
1018                 goto psx_create_err;
1019         }
1020
1021         /* copy return information to pRetData */
1022         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1023                         + le16_to_cpu(pSMBr->t2.DataOffset));
1024
1025         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1026         if (netfid)
1027                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1028         /* Let caller know file was created so we can set the mode. */
1029         /* Do we care about the CreateAction in any other cases? */
1030         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1031                 *pOplock |= CIFS_CREATE_ACTION;
1032         /* check to make sure response data is there */
1033         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1034                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1035                 cFYI(DBG2, ("unknown type"));
1036         } else {
1037                 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1038                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1039                         cERROR(1, ("Open response data too small"));
1040                         pRetData->Type = cpu_to_le32(-1);
1041                         goto psx_create_err;
1042                 }
1043                 memcpy((char *) pRetData,
1044                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1045                         sizeof(FILE_UNIX_BASIC_INFO));
1046         }
1047
1048 psx_create_err:
1049         cifs_buf_release(pSMB);
1050
1051         if (posix_flags & SMB_O_DIRECTORY)
1052                 cifs_stats_inc(&tcon->num_posixmkdirs);
1053         else
1054                 cifs_stats_inc(&tcon->num_posixopens);
1055
1056         if (rc == -EAGAIN)
1057                 goto PsxCreat;
1058
1059         return rc;
1060 }
1061
1062 static __u16 convert_disposition(int disposition)
1063 {
1064         __u16 ofun = 0;
1065
1066         switch (disposition) {
1067                 case FILE_SUPERSEDE:
1068                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1069                         break;
1070                 case FILE_OPEN:
1071                         ofun = SMBOPEN_OAPPEND;
1072                         break;
1073                 case FILE_CREATE:
1074                         ofun = SMBOPEN_OCREATE;
1075                         break;
1076                 case FILE_OPEN_IF:
1077                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1078                         break;
1079                 case FILE_OVERWRITE:
1080                         ofun = SMBOPEN_OTRUNC;
1081                         break;
1082                 case FILE_OVERWRITE_IF:
1083                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1084                         break;
1085                 default:
1086                         cFYI(1, ("unknown disposition %d", disposition));
1087                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1088         }
1089         return ofun;
1090 }
1091
1092 static int
1093 access_flags_to_smbopen_mode(const int access_flags)
1094 {
1095         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1096
1097         if (masked_flags == GENERIC_READ)
1098                 return SMBOPEN_READ;
1099         else if (masked_flags == GENERIC_WRITE)
1100                 return SMBOPEN_WRITE;
1101
1102         /* just go for read/write */
1103         return SMBOPEN_READWRITE;
1104 }
1105
1106 int
1107 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1108             const char *fileName, const int openDisposition,
1109             const int access_flags, const int create_options, __u16 *netfid,
1110             int *pOplock, FILE_ALL_INFO *pfile_info,
1111             const struct nls_table *nls_codepage, int remap)
1112 {
1113         int rc = -EACCES;
1114         OPENX_REQ *pSMB = NULL;
1115         OPENX_RSP *pSMBr = NULL;
1116         int bytes_returned;
1117         int name_len;
1118         __u16 count;
1119
1120 OldOpenRetry:
1121         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1122                       (void **) &pSMBr);
1123         if (rc)
1124                 return rc;
1125
1126         pSMB->AndXCommand = 0xFF;       /* none */
1127
1128         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1129                 count = 1;      /* account for one byte pad to word boundary */
1130                 name_len =
1131                    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1132                                     fileName, PATH_MAX, nls_codepage, remap);
1133                 name_len++;     /* trailing null */
1134                 name_len *= 2;
1135         } else {                /* BB improve check for buffer overruns BB */
1136                 count = 0;      /* no pad */
1137                 name_len = strnlen(fileName, PATH_MAX);
1138                 name_len++;     /* trailing null */
1139                 strncpy(pSMB->fileName, fileName, name_len);
1140         }
1141         if (*pOplock & REQ_OPLOCK)
1142                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1143         else if (*pOplock & REQ_BATCHOPLOCK)
1144                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1145
1146         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1147         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1148         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1149         /* set file as system file if special file such
1150            as fifo and server expecting SFU style and
1151            no Unix extensions */
1152
1153         if (create_options & CREATE_OPTION_SPECIAL)
1154                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1155         else /* BB FIXME BB */
1156                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1157
1158         if (create_options & CREATE_OPTION_READONLY)
1159                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1160
1161         /* BB FIXME BB */
1162 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1163                                                  CREATE_OPTIONS_MASK); */
1164         /* BB FIXME END BB */
1165
1166         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1167         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1168         count += name_len;
1169         pSMB->hdr.smb_buf_length += count;
1170
1171         pSMB->ByteCount = cpu_to_le16(count);
1172         /* long_op set to 1 to allow for oplock break timeouts */
1173         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1174                         (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1175         cifs_stats_inc(&tcon->num_opens);
1176         if (rc) {
1177                 cFYI(1, ("Error in Open = %d", rc));
1178         } else {
1179         /* BB verify if wct == 15 */
1180
1181 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1182
1183                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1184                 /* Let caller know file was created so we can set the mode. */
1185                 /* Do we care about the CreateAction in any other cases? */
1186         /* BB FIXME BB */
1187 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1188                         *pOplock |= CIFS_CREATE_ACTION; */
1189         /* BB FIXME END */
1190
1191                 if (pfile_info) {
1192                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1193                         pfile_info->LastAccessTime = 0; /* BB fixme */
1194                         pfile_info->LastWriteTime = 0; /* BB fixme */
1195                         pfile_info->ChangeTime = 0;  /* BB fixme */
1196                         pfile_info->Attributes =
1197                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1198                         /* the file_info buf is endian converted by caller */
1199                         pfile_info->AllocationSize =
1200                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1201                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1202                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1203                         pfile_info->DeletePending = 0;
1204                 }
1205         }
1206
1207         cifs_buf_release(pSMB);
1208         if (rc == -EAGAIN)
1209                 goto OldOpenRetry;
1210         return rc;
1211 }
1212
1213 int
1214 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1215             const char *fileName, const int openDisposition,
1216             const int access_flags, const int create_options, __u16 *netfid,
1217             int *pOplock, FILE_ALL_INFO *pfile_info,
1218             const struct nls_table *nls_codepage, int remap)
1219 {
1220         int rc = -EACCES;
1221         OPEN_REQ *pSMB = NULL;
1222         OPEN_RSP *pSMBr = NULL;
1223         int bytes_returned;
1224         int name_len;
1225         __u16 count;
1226
1227 openRetry:
1228         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1229                       (void **) &pSMBr);
1230         if (rc)
1231                 return rc;
1232
1233         pSMB->AndXCommand = 0xFF;       /* none */
1234
1235         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1236                 count = 1;      /* account for one byte pad to word boundary */
1237                 name_len =
1238                     cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1239                                      fileName, PATH_MAX, nls_codepage, remap);
1240                 name_len++;     /* trailing null */
1241                 name_len *= 2;
1242                 pSMB->NameLength = cpu_to_le16(name_len);
1243         } else {                /* BB improve check for buffer overruns BB */
1244                 count = 0;      /* no pad */
1245                 name_len = strnlen(fileName, PATH_MAX);
1246                 name_len++;     /* trailing null */
1247                 pSMB->NameLength = cpu_to_le16(name_len);
1248                 strncpy(pSMB->fileName, fileName, name_len);
1249         }
1250         if (*pOplock & REQ_OPLOCK)
1251                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1252         else if (*pOplock & REQ_BATCHOPLOCK)
1253                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1254         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1255         pSMB->AllocationSize = 0;
1256         /* set file as system file if special file such
1257            as fifo and server expecting SFU style and
1258            no Unix extensions */
1259         if (create_options & CREATE_OPTION_SPECIAL)
1260                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1261         else
1262                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1263
1264         /* XP does not handle ATTR_POSIX_SEMANTICS */
1265         /* but it helps speed up case sensitive checks for other
1266         servers such as Samba */
1267         if (tcon->ses->capabilities & CAP_UNIX)
1268                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1269
1270         if (create_options & CREATE_OPTION_READONLY)
1271                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1272
1273         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1274         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1275         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1276         /* BB Expirement with various impersonation levels and verify */
1277         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1278         pSMB->SecurityFlags =
1279             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1280
1281         count += name_len;
1282         pSMB->hdr.smb_buf_length += count;
1283
1284         pSMB->ByteCount = cpu_to_le16(count);
1285         /* long_op set to 1 to allow for oplock break timeouts */
1286         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1287                         (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1288         cifs_stats_inc(&tcon->num_opens);
1289         if (rc) {
1290                 cFYI(1, ("Error in Open = %d", rc));
1291         } else {
1292                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1293                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1294                 /* Let caller know file was created so we can set the mode. */
1295                 /* Do we care about the CreateAction in any other cases? */
1296                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1297                         *pOplock |= CIFS_CREATE_ACTION;
1298                 if (pfile_info) {
1299                         memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1300                                 36 /* CreationTime to Attributes */);
1301                         /* the file_info buf is endian converted by caller */
1302                         pfile_info->AllocationSize = pSMBr->AllocationSize;
1303                         pfile_info->EndOfFile = pSMBr->EndOfFile;
1304                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1305                         pfile_info->DeletePending = 0;
1306                 }
1307         }
1308
1309         cifs_buf_release(pSMB);
1310         if (rc == -EAGAIN)
1311                 goto openRetry;
1312         return rc;
1313 }
1314
1315 int
1316 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1317             const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1318             char **buf, int *pbuf_type)
1319 {
1320         int rc = -EACCES;
1321         READ_REQ *pSMB = NULL;
1322         READ_RSP *pSMBr = NULL;
1323         char *pReadData = NULL;
1324         int wct;
1325         int resp_buf_type = 0;
1326         struct kvec iov[1];
1327
1328         cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1329         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1330                 wct = 12;
1331         else {
1332                 wct = 10; /* old style read */
1333                 if ((lseek >> 32) > 0)  {
1334                         /* can not handle this big offset for old */
1335                         return -EIO;
1336                 }
1337         }
1338
1339         *nbytes = 0;
1340         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1341         if (rc)
1342                 return rc;
1343
1344         /* tcon and ses pointer are checked in smb_init */
1345         if (tcon->ses->server == NULL)
1346                 return -ECONNABORTED;
1347
1348         pSMB->AndXCommand = 0xFF;       /* none */
1349         pSMB->Fid = netfid;
1350         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1351         if (wct == 12)
1352                 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1353
1354         pSMB->Remaining = 0;
1355         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1356         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1357         if (wct == 12)
1358                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1359         else {
1360                 /* old style read */
1361                 struct smb_com_readx_req *pSMBW =
1362                         (struct smb_com_readx_req *)pSMB;
1363                 pSMBW->ByteCount = 0;
1364         }
1365
1366         iov[0].iov_base = (char *)pSMB;
1367         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1368         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1369                          &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1370         cifs_stats_inc(&tcon->num_reads);
1371         pSMBr = (READ_RSP *)iov[0].iov_base;
1372         if (rc) {
1373                 cERROR(1, ("Send error in read = %d", rc));
1374         } else {
1375                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1376                 data_length = data_length << 16;
1377                 data_length += le16_to_cpu(pSMBr->DataLength);
1378                 *nbytes = data_length;
1379
1380                 /*check that DataLength would not go beyond end of SMB */
1381                 if ((data_length > CIFSMaxBufSize)
1382                                 || (data_length > count)) {
1383                         cFYI(1, ("bad length %d for count %d",
1384                                  data_length, count));
1385                         rc = -EIO;
1386                         *nbytes = 0;
1387                 } else {
1388                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1389                                         le16_to_cpu(pSMBr->DataOffset);
1390 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1391                                 cERROR(1,("Faulting on read rc = %d",rc));
1392                                 rc = -EFAULT;
1393                         }*/ /* can not use copy_to_user when using page cache*/
1394                         if (*buf)
1395                                 memcpy(*buf, pReadData, data_length);
1396                 }
1397         }
1398
1399 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1400         if (*buf) {
1401                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1402                         cifs_small_buf_release(iov[0].iov_base);
1403                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1404                         cifs_buf_release(iov[0].iov_base);
1405         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1406                 /* return buffer to caller to free */
1407                 *buf = iov[0].iov_base;
1408                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1409                         *pbuf_type = CIFS_SMALL_BUFFER;
1410                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1411                         *pbuf_type = CIFS_LARGE_BUFFER;
1412         } /* else no valid buffer on return - leave as null */
1413
1414         /* Note: On -EAGAIN error only caller can retry on handle based calls
1415                 since file handle passed in no longer valid */
1416         return rc;
1417 }
1418
1419
1420 int
1421 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1422              const int netfid, const unsigned int count,
1423              const __u64 offset, unsigned int *nbytes, const char *buf,
1424              const char __user *ubuf, const int long_op)
1425 {
1426         int rc = -EACCES;
1427         WRITE_REQ *pSMB = NULL;
1428         WRITE_RSP *pSMBr = NULL;
1429         int bytes_returned, wct;
1430         __u32 bytes_sent;
1431         __u16 byte_count;
1432
1433         /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1434         if (tcon->ses == NULL)
1435                 return -ECONNABORTED;
1436
1437         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1438                 wct = 14;
1439         else {
1440                 wct = 12;
1441                 if ((offset >> 32) > 0) {
1442                         /* can not handle big offset for old srv */
1443                         return -EIO;
1444                 }
1445         }
1446
1447         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1448                       (void **) &pSMBr);
1449         if (rc)
1450                 return rc;
1451         /* tcon and ses pointer are checked in smb_init */
1452         if (tcon->ses->server == NULL)
1453                 return -ECONNABORTED;
1454
1455         pSMB->AndXCommand = 0xFF;       /* none */
1456         pSMB->Fid = netfid;
1457         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1458         if (wct == 14)
1459                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1460
1461         pSMB->Reserved = 0xFFFFFFFF;
1462         pSMB->WriteMode = 0;
1463         pSMB->Remaining = 0;
1464
1465         /* Can increase buffer size if buffer is big enough in some cases ie we
1466         can send more if LARGE_WRITE_X capability returned by the server and if
1467         our buffer is big enough or if we convert to iovecs on socket writes
1468         and eliminate the copy to the CIFS buffer */
1469         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1470                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1471         } else {
1472                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1473                          & ~0xFF;
1474         }
1475
1476         if (bytes_sent > count)
1477                 bytes_sent = count;
1478         pSMB->DataOffset =
1479                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1480         if (buf)
1481                 memcpy(pSMB->Data, buf, bytes_sent);
1482         else if (ubuf) {
1483                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1484                         cifs_buf_release(pSMB);
1485                         return -EFAULT;
1486                 }
1487         } else if (count != 0) {
1488                 /* No buffer */
1489                 cifs_buf_release(pSMB);
1490                 return -EINVAL;
1491         } /* else setting file size with write of zero bytes */
1492         if (wct == 14)
1493                 byte_count = bytes_sent + 1; /* pad */
1494         else /* wct == 12 */
1495                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1496
1497         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1498         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1499         pSMB->hdr.smb_buf_length += byte_count;
1500
1501         if (wct == 14)
1502                 pSMB->ByteCount = cpu_to_le16(byte_count);
1503         else { /* old style write has byte count 4 bytes earlier
1504                   so 4 bytes pad  */
1505                 struct smb_com_writex_req *pSMBW =
1506                         (struct smb_com_writex_req *)pSMB;
1507                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1508         }
1509
1510         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1511                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1512         cifs_stats_inc(&tcon->num_writes);
1513         if (rc) {
1514                 cFYI(1, ("Send error in write = %d", rc));
1515                 *nbytes = 0;
1516         } else {
1517                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1518                 *nbytes = (*nbytes) << 16;
1519                 *nbytes += le16_to_cpu(pSMBr->Count);
1520         }
1521
1522         cifs_buf_release(pSMB);
1523
1524         /* Note: On -EAGAIN error only caller can retry on handle based calls
1525                 since file handle passed in no longer valid */
1526
1527         return rc;
1528 }
1529
1530 int
1531 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1532              const int netfid, const unsigned int count,
1533              const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1534              int n_vec, const int long_op)
1535 {
1536         int rc = -EACCES;
1537         WRITE_REQ *pSMB = NULL;
1538         int wct;
1539         int smb_hdr_len;
1540         int resp_buf_type = 0;
1541
1542         *nbytes = 0;
1543
1544         cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1545
1546         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1547                 wct = 14;
1548         } else {
1549                 wct = 12;
1550                 if ((offset >> 32) > 0) {
1551                         /* can not handle big offset for old srv */
1552                         return -EIO;
1553                 }
1554         }
1555         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1556         if (rc)
1557                 return rc;
1558         /* tcon and ses pointer are checked in smb_init */
1559         if (tcon->ses->server == NULL)
1560                 return -ECONNABORTED;
1561
1562         pSMB->AndXCommand = 0xFF;       /* none */
1563         pSMB->Fid = netfid;
1564         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1565         if (wct == 14)
1566                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1567         pSMB->Reserved = 0xFFFFFFFF;
1568         pSMB->WriteMode = 0;
1569         pSMB->Remaining = 0;
1570
1571         pSMB->DataOffset =
1572             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1573
1574         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1575         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1576         smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1577         if (wct == 14)
1578                 pSMB->hdr.smb_buf_length += count+1;
1579         else /* wct == 12 */
1580                 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1581         if (wct == 14)
1582                 pSMB->ByteCount = cpu_to_le16(count + 1);
1583         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1584                 struct smb_com_writex_req *pSMBW =
1585                                 (struct smb_com_writex_req *)pSMB;
1586                 pSMBW->ByteCount = cpu_to_le16(count + 5);
1587         }
1588         iov[0].iov_base = pSMB;
1589         if (wct == 14)
1590                 iov[0].iov_len = smb_hdr_len + 4;
1591         else /* wct == 12 pad bigger by four bytes */
1592                 iov[0].iov_len = smb_hdr_len + 8;
1593
1594
1595         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1596                           long_op);
1597         cifs_stats_inc(&tcon->num_writes);
1598         if (rc) {
1599                 cFYI(1, ("Send error Write2 = %d", rc));
1600         } else if (resp_buf_type == 0) {
1601                 /* presumably this can not happen, but best to be safe */
1602                 rc = -EIO;
1603         } else {
1604                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1605                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1606                 *nbytes = (*nbytes) << 16;
1607                 *nbytes += le16_to_cpu(pSMBr->Count);
1608         }
1609
1610 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1611         if (resp_buf_type == CIFS_SMALL_BUFFER)
1612                 cifs_small_buf_release(iov[0].iov_base);
1613         else if (resp_buf_type == CIFS_LARGE_BUFFER)
1614                 cifs_buf_release(iov[0].iov_base);
1615
1616         /* Note: On -EAGAIN error only caller can retry on handle based calls
1617                 since file handle passed in no longer valid */
1618
1619         return rc;
1620 }
1621
1622
1623 int
1624 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1625             const __u16 smb_file_id, const __u64 len,
1626             const __u64 offset, const __u32 numUnlock,
1627             const __u32 numLock, const __u8 lockType, const bool waitFlag)
1628 {
1629         int rc = 0;
1630         LOCK_REQ *pSMB = NULL;
1631 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1632         int bytes_returned;
1633         int timeout = 0;
1634         __u16 count;
1635
1636         cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1637         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1638
1639         if (rc)
1640                 return rc;
1641
1642         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1643                 timeout = CIFS_ASYNC_OP; /* no response expected */
1644                 pSMB->Timeout = 0;
1645         } else if (waitFlag) {
1646                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1647                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1648         } else {
1649                 pSMB->Timeout = 0;
1650         }
1651
1652         pSMB->NumberOfLocks = cpu_to_le16(numLock);
1653         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1654         pSMB->LockType = lockType;
1655         pSMB->AndXCommand = 0xFF;       /* none */
1656         pSMB->Fid = smb_file_id; /* netfid stays le */
1657
1658         if ((numLock != 0) || (numUnlock != 0)) {
1659                 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1660                 /* BB where to store pid high? */
1661                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1662                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1663                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1664                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1665                 count = sizeof(LOCKING_ANDX_RANGE);
1666         } else {
1667                 /* oplock break */
1668                 count = 0;
1669         }
1670         pSMB->hdr.smb_buf_length += count;
1671         pSMB->ByteCount = cpu_to_le16(count);
1672
1673         if (waitFlag) {
1674                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1675                         (struct smb_hdr *) pSMB, &bytes_returned);
1676                 cifs_small_buf_release(pSMB);
1677         } else {
1678                 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1679                                       timeout);
1680                 /* SMB buffer freed by function above */
1681         }
1682         cifs_stats_inc(&tcon->num_locks);
1683         if (rc)
1684                 cFYI(1, ("Send error in Lock = %d", rc));
1685
1686         /* Note: On -EAGAIN error only caller can retry on handle based calls
1687         since file handle passed in no longer valid */
1688         return rc;
1689 }
1690
1691 int
1692 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1693                 const __u16 smb_file_id, const int get_flag, const __u64 len,
1694                 struct file_lock *pLockData, const __u16 lock_type,
1695                 const bool waitFlag)
1696 {
1697         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1698         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1699         struct cifs_posix_lock *parm_data;
1700         int rc = 0;
1701         int timeout = 0;
1702         int bytes_returned = 0;
1703         int resp_buf_type = 0;
1704         __u16 params, param_offset, offset, byte_count, count;
1705         struct kvec iov[1];
1706
1707         cFYI(1, ("Posix Lock"));
1708
1709         if (pLockData == NULL)
1710                 return -EINVAL;
1711
1712         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1713
1714         if (rc)
1715                 return rc;
1716
1717         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1718
1719         params = 6;
1720         pSMB->MaxSetupCount = 0;
1721         pSMB->Reserved = 0;
1722         pSMB->Flags = 0;
1723         pSMB->Reserved2 = 0;
1724         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1725         offset = param_offset + params;
1726
1727         count = sizeof(struct cifs_posix_lock);
1728         pSMB->MaxParameterCount = cpu_to_le16(2);
1729         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1730         pSMB->SetupCount = 1;
1731         pSMB->Reserved3 = 0;
1732         if (get_flag)
1733                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1734         else
1735                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1736         byte_count = 3 /* pad */  + params + count;
1737         pSMB->DataCount = cpu_to_le16(count);
1738         pSMB->ParameterCount = cpu_to_le16(params);
1739         pSMB->TotalDataCount = pSMB->DataCount;
1740         pSMB->TotalParameterCount = pSMB->ParameterCount;
1741         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1742         parm_data = (struct cifs_posix_lock *)
1743                         (((char *) &pSMB->hdr.Protocol) + offset);
1744
1745         parm_data->lock_type = cpu_to_le16(lock_type);
1746         if (waitFlag) {
1747                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1748                 parm_data->lock_flags = cpu_to_le16(1);
1749                 pSMB->Timeout = cpu_to_le32(-1);
1750         } else
1751                 pSMB->Timeout = 0;
1752
1753         parm_data->pid = cpu_to_le32(current->tgid);
1754         parm_data->start = cpu_to_le64(pLockData->fl_start);
1755         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
1756
1757         pSMB->DataOffset = cpu_to_le16(offset);
1758         pSMB->Fid = smb_file_id;
1759         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1760         pSMB->Reserved4 = 0;
1761         pSMB->hdr.smb_buf_length += byte_count;
1762         pSMB->ByteCount = cpu_to_le16(byte_count);
1763         if (waitFlag) {
1764                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1765                         (struct smb_hdr *) pSMBr, &bytes_returned);
1766         } else {
1767                 iov[0].iov_base = (char *)pSMB;
1768                 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1769                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1770                                 &resp_buf_type, timeout);
1771                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1772                                 not try to free it twice below on exit */
1773                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1774         }
1775
1776         if (rc) {
1777                 cFYI(1, ("Send error in Posix Lock = %d", rc));
1778         } else if (get_flag) {
1779                 /* lock structure can be returned on get */
1780                 __u16 data_offset;
1781                 __u16 data_count;
1782                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1783
1784                 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1785                         rc = -EIO;      /* bad smb */
1786                         goto plk_err_exit;
1787                 }
1788                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1789                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
1790                 if (data_count < sizeof(struct cifs_posix_lock)) {
1791                         rc = -EIO;
1792                         goto plk_err_exit;
1793                 }
1794                 parm_data = (struct cifs_posix_lock *)
1795                         ((char *)&pSMBr->hdr.Protocol + data_offset);
1796                 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1797                         pLockData->fl_type = F_UNLCK;
1798         }
1799
1800 plk_err_exit:
1801         if (pSMB)
1802                 cifs_small_buf_release(pSMB);
1803
1804         if (resp_buf_type == CIFS_SMALL_BUFFER)
1805                 cifs_small_buf_release(iov[0].iov_base);
1806         else if (resp_buf_type == CIFS_LARGE_BUFFER)
1807                 cifs_buf_release(iov[0].iov_base);
1808
1809         /* Note: On -EAGAIN error only caller can retry on handle based calls
1810            since file handle passed in no longer valid */
1811
1812         return rc;
1813 }
1814
1815
1816 int
1817 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1818 {
1819         int rc = 0;
1820         CLOSE_REQ *pSMB = NULL;
1821         cFYI(1, ("In CIFSSMBClose"));
1822
1823 /* do not retry on dead session on close */
1824         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1825         if (rc == -EAGAIN)
1826                 return 0;
1827         if (rc)
1828                 return rc;
1829
1830         pSMB->FileID = (__u16) smb_file_id;
1831         pSMB->LastWriteTime = 0xFFFFFFFF;
1832         pSMB->ByteCount = 0;
1833         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1834         cifs_stats_inc(&tcon->num_closes);
1835         if (rc) {
1836                 if (rc != -EINTR) {
1837                         /* EINTR is expected when user ctl-c to kill app */
1838                         cERROR(1, ("Send error in Close = %d", rc));
1839                 }
1840         }
1841
1842         /* Since session is dead, file will be closed on server already */
1843         if (rc == -EAGAIN)
1844                 rc = 0;
1845
1846         return rc;
1847 }
1848
1849 int
1850 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1851 {
1852         int rc = 0;
1853         FLUSH_REQ *pSMB = NULL;
1854         cFYI(1, ("In CIFSSMBFlush"));
1855
1856         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1857         if (rc)
1858                 return rc;
1859
1860         pSMB->FileID = (__u16) smb_file_id;
1861         pSMB->ByteCount = 0;
1862         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1863         cifs_stats_inc(&tcon->num_flushes);
1864         if (rc)
1865                 cERROR(1, ("Send error in Flush = %d", rc));
1866
1867         return rc;
1868 }
1869
1870 int
1871 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1872               const char *fromName, const char *toName,
1873               const struct nls_table *nls_codepage, int remap)
1874 {
1875         int rc = 0;
1876         RENAME_REQ *pSMB = NULL;
1877         RENAME_RSP *pSMBr = NULL;
1878         int bytes_returned;
1879         int name_len, name_len2;
1880         __u16 count;
1881
1882         cFYI(1, ("In CIFSSMBRename"));
1883 renameRetry:
1884         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1885                       (void **) &pSMBr);
1886         if (rc)
1887                 return rc;
1888
1889         pSMB->BufferFormat = 0x04;
1890         pSMB->SearchAttributes =
1891             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1892                         ATTR_DIRECTORY);
1893
1894         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1895                 name_len =
1896                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1897                                      PATH_MAX, nls_codepage, remap);
1898                 name_len++;     /* trailing null */
1899                 name_len *= 2;
1900                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1901         /* protocol requires ASCII signature byte on Unicode string */
1902                 pSMB->OldFileName[name_len + 1] = 0x00;
1903                 name_len2 =
1904                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1905                                      toName, PATH_MAX, nls_codepage, remap);
1906                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1907                 name_len2 *= 2; /* convert to bytes */
1908         } else {        /* BB improve the check for buffer overruns BB */
1909                 name_len = strnlen(fromName, PATH_MAX);
1910                 name_len++;     /* trailing null */
1911                 strncpy(pSMB->OldFileName, fromName, name_len);
1912                 name_len2 = strnlen(toName, PATH_MAX);
1913                 name_len2++;    /* trailing null */
1914                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
1915                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1916                 name_len2++;    /* trailing null */
1917                 name_len2++;    /* signature byte */
1918         }
1919
1920         count = 1 /* 1st signature byte */  + name_len + name_len2;
1921         pSMB->hdr.smb_buf_length += count;
1922         pSMB->ByteCount = cpu_to_le16(count);
1923
1924         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1925                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1926         cifs_stats_inc(&tcon->num_renames);
1927         if (rc)
1928                 cFYI(1, ("Send error in rename = %d", rc));
1929
1930         cifs_buf_release(pSMB);
1931
1932         if (rc == -EAGAIN)
1933                 goto renameRetry;
1934
1935         return rc;
1936 }
1937
1938 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
1939                 int netfid, const char *target_name,
1940                 const struct nls_table *nls_codepage, int remap)
1941 {
1942         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1943         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1944         struct set_file_rename *rename_info;
1945         char *data_offset;
1946         char dummy_string[30];
1947         int rc = 0;
1948         int bytes_returned = 0;
1949         int len_of_str;
1950         __u16 params, param_offset, offset, count, byte_count;
1951
1952         cFYI(1, ("Rename to File by handle"));
1953         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1954                         (void **) &pSMBr);
1955         if (rc)
1956                 return rc;
1957
1958         params = 6;
1959         pSMB->MaxSetupCount = 0;
1960         pSMB->Reserved = 0;
1961         pSMB->Flags = 0;
1962         pSMB->Timeout = 0;
1963         pSMB->Reserved2 = 0;
1964         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1965         offset = param_offset + params;
1966
1967         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1968         rename_info = (struct set_file_rename *) data_offset;
1969         pSMB->MaxParameterCount = cpu_to_le16(2);
1970         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1971         pSMB->SetupCount = 1;
1972         pSMB->Reserved3 = 0;
1973         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1974         byte_count = 3 /* pad */  + params;
1975         pSMB->ParameterCount = cpu_to_le16(params);
1976         pSMB->TotalParameterCount = pSMB->ParameterCount;
1977         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1978         pSMB->DataOffset = cpu_to_le16(offset);
1979         /* construct random name ".cifs_tmp<inodenum><mid>" */
1980         rename_info->overwrite = cpu_to_le32(1);
1981         rename_info->root_fid  = 0;
1982         /* unicode only call */
1983         if (target_name == NULL) {
1984                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
1985                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1986                                         dummy_string, 24, nls_codepage, remap);
1987         } else {
1988                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1989                                         target_name, PATH_MAX, nls_codepage,
1990                                         remap);
1991         }
1992         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1993         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
1994         byte_count += count;
1995         pSMB->DataCount = cpu_to_le16(count);
1996         pSMB->TotalDataCount = pSMB->DataCount;
1997         pSMB->Fid = netfid;
1998         pSMB->InformationLevel =
1999                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2000         pSMB->Reserved4 = 0;
2001         pSMB->hdr.smb_buf_length += byte_count;
2002         pSMB->ByteCount = cpu_to_le16(byte_count);
2003         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2004                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2005         cifs_stats_inc(&pTcon->num_t2renames);
2006         if (rc)
2007                 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2008
2009         cifs_buf_release(pSMB);
2010
2011         /* Note: On -EAGAIN error only caller can retry on handle based calls
2012                 since file handle passed in no longer valid */
2013
2014         return rc;
2015 }
2016
2017 int
2018 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2019             const __u16 target_tid, const char *toName, const int flags,
2020             const struct nls_table *nls_codepage, int remap)
2021 {
2022         int rc = 0;
2023         COPY_REQ *pSMB = NULL;
2024         COPY_RSP *pSMBr = NULL;
2025         int bytes_returned;
2026         int name_len, name_len2;
2027         __u16 count;
2028
2029         cFYI(1, ("In CIFSSMBCopy"));
2030 copyRetry:
2031         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2032                         (void **) &pSMBr);
2033         if (rc)
2034                 return rc;
2035
2036         pSMB->BufferFormat = 0x04;
2037         pSMB->Tid2 = target_tid;
2038
2039         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2040
2041         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2042                 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2043                                             fromName, PATH_MAX, nls_codepage,
2044                                             remap);
2045                 name_len++;     /* trailing null */
2046                 name_len *= 2;
2047                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2048                 /* protocol requires ASCII signature byte on Unicode string */
2049                 pSMB->OldFileName[name_len + 1] = 0x00;
2050                 name_len2 =
2051                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2052                                 toName, PATH_MAX, nls_codepage, remap);
2053                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2054                 name_len2 *= 2; /* convert to bytes */
2055         } else {        /* BB improve the check for buffer overruns BB */
2056                 name_len = strnlen(fromName, PATH_MAX);
2057                 name_len++;     /* trailing null */
2058                 strncpy(pSMB->OldFileName, fromName, name_len);
2059                 name_len2 = strnlen(toName, PATH_MAX);
2060                 name_len2++;    /* trailing null */
2061                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2062                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2063                 name_len2++;    /* trailing null */
2064                 name_len2++;    /* signature byte */
2065         }
2066
2067         count = 1 /* 1st signature byte */  + name_len + name_len2;
2068         pSMB->hdr.smb_buf_length += count;
2069         pSMB->ByteCount = cpu_to_le16(count);
2070
2071         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2072                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2073         if (rc) {
2074                 cFYI(1, ("Send error in copy = %d with %d files copied",
2075                         rc, le16_to_cpu(pSMBr->CopyCount)));
2076         }
2077         cifs_buf_release(pSMB);
2078
2079         if (rc == -EAGAIN)
2080                 goto copyRetry;
2081
2082         return rc;
2083 }
2084
2085 int
2086 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2087                       const char *fromName, const char *toName,
2088                       const struct nls_table *nls_codepage)
2089 {
2090         TRANSACTION2_SPI_REQ *pSMB = NULL;
2091         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2092         char *data_offset;
2093         int name_len;
2094         int name_len_target;
2095         int rc = 0;
2096         int bytes_returned = 0;
2097         __u16 params, param_offset, offset, byte_count;
2098
2099         cFYI(1, ("In Symlink Unix style"));
2100 createSymLinkRetry:
2101         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2102                       (void **) &pSMBr);
2103         if (rc)
2104                 return rc;
2105
2106         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2107                 name_len =
2108                     cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2109                                   /* find define for this maxpathcomponent */
2110                                   , nls_codepage);
2111                 name_len++;     /* trailing null */
2112                 name_len *= 2;
2113
2114         } else {        /* BB improve the check for buffer overruns BB */
2115                 name_len = strnlen(fromName, PATH_MAX);
2116                 name_len++;     /* trailing null */
2117                 strncpy(pSMB->FileName, fromName, name_len);
2118         }
2119         params = 6 + name_len;
2120         pSMB->MaxSetupCount = 0;
2121         pSMB->Reserved = 0;
2122         pSMB->Flags = 0;
2123         pSMB->Timeout = 0;
2124         pSMB->Reserved2 = 0;
2125         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2126                                 InformationLevel) - 4;
2127         offset = param_offset + params;
2128
2129         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2130         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2131                 name_len_target =
2132                     cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2133                                   /* find define for this maxpathcomponent */
2134                                   , nls_codepage);
2135                 name_len_target++;      /* trailing null */
2136                 name_len_target *= 2;
2137         } else {        /* BB improve the check for buffer overruns BB */
2138                 name_len_target = strnlen(toName, PATH_MAX);
2139                 name_len_target++;      /* trailing null */
2140                 strncpy(data_offset, toName, name_len_target);
2141         }
2142
2143         pSMB->MaxParameterCount = cpu_to_le16(2);
2144         /* BB find exact max on data count below from sess */
2145         pSMB->MaxDataCount = cpu_to_le16(1000);
2146         pSMB->SetupCount = 1;
2147         pSMB->Reserved3 = 0;
2148         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2149         byte_count = 3 /* pad */  + params + name_len_target;
2150         pSMB->DataCount = cpu_to_le16(name_len_target);
2151         pSMB->ParameterCount = cpu_to_le16(params);
2152         pSMB->TotalDataCount = pSMB->DataCount;
2153         pSMB->TotalParameterCount = pSMB->ParameterCount;
2154         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2155         pSMB->DataOffset = cpu_to_le16(offset);
2156         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2157         pSMB->Reserved4 = 0;
2158         pSMB->hdr.smb_buf_length += byte_count;
2159         pSMB->ByteCount = cpu_to_le16(byte_count);
2160         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2161                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2162         cifs_stats_inc(&tcon->num_symlinks);
2163         if (rc)
2164                 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2165
2166         cifs_buf_release(pSMB);
2167
2168         if (rc == -EAGAIN)
2169                 goto createSymLinkRetry;
2170
2171         return rc;
2172 }
2173
2174 int
2175 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2176                        const char *fromName, const char *toName,
2177                        const struct nls_table *nls_codepage, int remap)
2178 {
2179         TRANSACTION2_SPI_REQ *pSMB = NULL;
2180         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2181         char *data_offset;
2182         int name_len;
2183         int name_len_target;
2184         int rc = 0;
2185         int bytes_returned = 0;
2186         __u16 params, param_offset, offset, byte_count;
2187
2188         cFYI(1, ("In Create Hard link Unix style"));
2189 createHardLinkRetry:
2190         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2191                       (void **) &pSMBr);
2192         if (rc)
2193                 return rc;
2194
2195         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2196                 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2197                                             PATH_MAX, nls_codepage, remap);
2198                 name_len++;     /* trailing null */
2199                 name_len *= 2;
2200
2201         } else {        /* BB improve the check for buffer overruns BB */
2202                 name_len = strnlen(toName, PATH_MAX);
2203                 name_len++;     /* trailing null */
2204                 strncpy(pSMB->FileName, toName, name_len);
2205         }
2206         params = 6 + name_len;
2207         pSMB->MaxSetupCount = 0;
2208         pSMB->Reserved = 0;
2209         pSMB->Flags = 0;
2210         pSMB->Timeout = 0;
2211         pSMB->Reserved2 = 0;
2212         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2213                                 InformationLevel) - 4;
2214         offset = param_offset + params;
2215
2216         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2217         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2218                 name_len_target =
2219                     cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2220                                      nls_codepage, remap);
2221                 name_len_target++;      /* trailing null */
2222                 name_len_target *= 2;
2223         } else {        /* BB improve the check for buffer overruns BB */
2224                 name_len_target = strnlen(fromName, PATH_MAX);
2225                 name_len_target++;      /* trailing null */
2226                 strncpy(data_offset, fromName, name_len_target);
2227         }
2228
2229         pSMB->MaxParameterCount = cpu_to_le16(2);
2230         /* BB find exact max on data count below from sess*/
2231         pSMB->MaxDataCount = cpu_to_le16(1000);
2232         pSMB->SetupCount = 1;
2233         pSMB->Reserved3 = 0;
2234         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2235         byte_count = 3 /* pad */  + params + name_len_target;
2236         pSMB->ParameterCount = cpu_to_le16(params);
2237         pSMB->TotalParameterCount = pSMB->ParameterCount;
2238         pSMB->DataCount = cpu_to_le16(name_len_target);
2239         pSMB->TotalDataCount = pSMB->DataCount;
2240         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2241         pSMB->DataOffset = cpu_to_le16(offset);
2242         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2243         pSMB->Reserved4 = 0;
2244         pSMB->hdr.smb_buf_length += byte_count;
2245         pSMB->ByteCount = cpu_to_le16(byte_count);
2246         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2247                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2248         cifs_stats_inc(&tcon->num_hardlinks);
2249         if (rc)
2250                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2251
2252         cifs_buf_release(pSMB);
2253         if (rc == -EAGAIN)
2254                 goto createHardLinkRetry;
2255
2256         return rc;
2257 }
2258
2259 int
2260 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2261                    const char *fromName, const char *toName,
2262                    const struct nls_table *nls_codepage, int remap)
2263 {
2264         int rc = 0;
2265         NT_RENAME_REQ *pSMB = NULL;
2266         RENAME_RSP *pSMBr = NULL;
2267         int bytes_returned;
2268         int name_len, name_len2;
2269         __u16 count;
2270
2271         cFYI(1, ("In CIFSCreateHardLink"));
2272 winCreateHardLinkRetry:
2273
2274         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2275                       (void **) &pSMBr);
2276         if (rc)
2277                 return rc;
2278
2279         pSMB->SearchAttributes =
2280             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2281                         ATTR_DIRECTORY);
2282         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2283         pSMB->ClusterCount = 0;
2284
2285         pSMB->BufferFormat = 0x04;
2286
2287         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2288                 name_len =
2289                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2290                                      PATH_MAX, nls_codepage, remap);
2291                 name_len++;     /* trailing null */
2292                 name_len *= 2;
2293
2294                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2295                 pSMB->OldFileName[name_len] = 0x04;
2296                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2297                 name_len2 =
2298                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2299                                      toName, PATH_MAX, nls_codepage, remap);
2300                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2301                 name_len2 *= 2; /* convert to bytes */
2302         } else {        /* BB improve the check for buffer overruns BB */
2303                 name_len = strnlen(fromName, PATH_MAX);
2304                 name_len++;     /* trailing null */
2305                 strncpy(pSMB->OldFileName, fromName, name_len);
2306                 name_len2 = strnlen(toName, PATH_MAX);
2307                 name_len2++;    /* trailing null */
2308                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2309                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2310                 name_len2++;    /* trailing null */
2311                 name_len2++;    /* signature byte */
2312         }
2313
2314         count = 1 /* string type byte */  + name_len + name_len2;
2315         pSMB->hdr.smb_buf_length += count;
2316         pSMB->ByteCount = cpu_to_le16(count);
2317
2318         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2319                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2320         cifs_stats_inc(&tcon->num_hardlinks);
2321         if (rc)
2322                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2323
2324         cifs_buf_release(pSMB);
2325         if (rc == -EAGAIN)
2326                 goto winCreateHardLinkRetry;
2327
2328         return rc;
2329 }
2330
2331 int
2332 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2333                         const unsigned char *searchName, char **symlinkinfo,
2334                         const struct nls_table *nls_codepage)
2335 {
2336 /* SMB_QUERY_FILE_UNIX_LINK */
2337         TRANSACTION2_QPI_REQ *pSMB = NULL;
2338         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2339         int rc = 0;
2340         int bytes_returned;
2341         int name_len;
2342         __u16 params, byte_count;
2343         char *data_start;
2344
2345         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2346
2347 querySymLinkRetry:
2348         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2349                       (void **) &pSMBr);
2350         if (rc)
2351                 return rc;
2352
2353         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2354                 name_len =
2355                     cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2356                                   PATH_MAX, nls_codepage);
2357                 name_len++;     /* trailing null */
2358                 name_len *= 2;
2359         } else {        /* BB improve the check for buffer overruns BB */
2360                 name_len = strnlen(searchName, PATH_MAX);
2361                 name_len++;     /* trailing null */
2362                 strncpy(pSMB->FileName, searchName, name_len);
2363         }
2364
2365         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2366         pSMB->TotalDataCount = 0;
2367         pSMB->MaxParameterCount = cpu_to_le16(2);
2368         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2369         pSMB->MaxSetupCount = 0;
2370         pSMB->Reserved = 0;
2371         pSMB->Flags = 0;
2372         pSMB->Timeout = 0;
2373         pSMB->Reserved2 = 0;
2374         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2375         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2376         pSMB->DataCount = 0;
2377         pSMB->DataOffset = 0;
2378         pSMB->SetupCount = 1;
2379         pSMB->Reserved3 = 0;
2380         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2381         byte_count = params + 1 /* pad */ ;
2382         pSMB->TotalParameterCount = cpu_to_le16(params);
2383         pSMB->ParameterCount = pSMB->TotalParameterCount;
2384         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2385         pSMB->Reserved4 = 0;
2386         pSMB->hdr.smb_buf_length += byte_count;
2387         pSMB->ByteCount = cpu_to_le16(byte_count);
2388
2389         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2390                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2391         if (rc) {
2392                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2393         } else {
2394                 /* decode response */
2395
2396                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2397                 /* BB also check enough total bytes returned */
2398                 if (rc || (pSMBr->ByteCount < 2))
2399                         rc = -EIO;
2400                 else {
2401                         bool is_unicode;
2402                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2403
2404                         data_start = ((char *) &pSMBr->hdr.Protocol) +
2405                                            le16_to_cpu(pSMBr->t2.DataOffset);
2406
2407                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2408                                 is_unicode = true;
2409                         else
2410                                 is_unicode = false;
2411
2412                         /* BB FIXME investigate remapping reserved chars here */
2413                         *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2414                                                     is_unicode, nls_codepage);
2415                         if (!*symlinkinfo)
2416                                 rc = -ENOMEM;
2417                 }
2418         }
2419         cifs_buf_release(pSMB);
2420         if (rc == -EAGAIN)
2421                 goto querySymLinkRetry;
2422         return rc;
2423 }
2424
2425 #ifdef CONFIG_CIFS_EXPERIMENTAL
2426 /* Initialize NT TRANSACT SMB into small smb request buffer.
2427    This assumes that all NT TRANSACTS that we init here have
2428    total parm and data under about 400 bytes (to fit in small cifs
2429    buffer size), which is the case so far, it easily fits. NB:
2430         Setup words themselves and ByteCount
2431         MaxSetupCount (size of returned setup area) and
2432         MaxParameterCount (returned parms size) must be set by caller */
2433 static int
2434 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2435                    const int parm_len, struct cifsTconInfo *tcon,
2436                    void **ret_buf)
2437 {
2438         int rc;
2439         __u32 temp_offset;
2440         struct smb_com_ntransact_req *pSMB;
2441
2442         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2443                                 (void **)&pSMB);
2444         if (rc)
2445                 return rc;
2446         *ret_buf = (void *)pSMB;
2447         pSMB->Reserved = 0;
2448         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2449         pSMB->TotalDataCount  = 0;
2450         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2451                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2452         pSMB->ParameterCount = pSMB->TotalParameterCount;
2453         pSMB->DataCount  = pSMB->TotalDataCount;
2454         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2455                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
2456         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2457         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2458         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2459         pSMB->SubCommand = cpu_to_le16(sub_command);
2460         return 0;
2461 }
2462
2463 static int
2464 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2465                    __u32 *pparmlen, __u32 *pdatalen)
2466 {
2467         char *end_of_smb;
2468         __u32 data_count, data_offset, parm_count, parm_offset;
2469         struct smb_com_ntransact_rsp *pSMBr;
2470
2471         *pdatalen = 0;
2472         *pparmlen = 0;
2473
2474         if (buf == NULL)
2475                 return -EINVAL;
2476
2477         pSMBr = (struct smb_com_ntransact_rsp *)buf;
2478
2479         /* ByteCount was converted from little endian in SendReceive */
2480         end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2481                         (char *)&pSMBr->ByteCount;
2482
2483         data_offset = le32_to_cpu(pSMBr->DataOffset);
2484         data_count = le32_to_cpu(pSMBr->DataCount);
2485         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2486         parm_count = le32_to_cpu(pSMBr->ParameterCount);
2487
2488         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2489         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2490
2491         /* should we also check that parm and data areas do not overlap? */
2492         if (*ppparm > end_of_smb) {
2493                 cFYI(1, ("parms start after end of smb"));
2494                 return -EINVAL;
2495         } else if (parm_count + *ppparm > end_of_smb) {
2496                 cFYI(1, ("parm end after end of smb"));
2497                 return -EINVAL;
2498         } else if (*ppdata > end_of_smb) {
2499                 cFYI(1, ("data starts after end of smb"));
2500                 return -EINVAL;
2501         } else if (data_count + *ppdata > end_of_smb) {
2502                 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2503                         *ppdata, data_count, (data_count + *ppdata),
2504                         end_of_smb, pSMBr));
2505                 return -EINVAL;
2506         } else if (parm_count + data_count > pSMBr->ByteCount) {
2507                 cFYI(1, ("parm count and data count larger than SMB"));
2508                 return -EINVAL;
2509         }
2510         *pdatalen = data_count;
2511         *pparmlen = parm_count;
2512         return 0;
2513 }
2514
2515 int
2516 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2517                         const unsigned char *searchName,
2518                         char *symlinkinfo, const int buflen, __u16 fid,
2519                         const struct nls_table *nls_codepage)
2520 {
2521         int rc = 0;
2522         int bytes_returned;
2523         struct smb_com_transaction_ioctl_req *pSMB;
2524         struct smb_com_transaction_ioctl_rsp *pSMBr;
2525
2526         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2527         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2528                       (void **) &pSMBr);
2529         if (rc)
2530                 return rc;
2531
2532         pSMB->TotalParameterCount = 0 ;
2533         pSMB->TotalDataCount = 0;
2534         pSMB->MaxParameterCount = cpu_to_le32(2);
2535         /* BB find exact data count max from sess structure BB */
2536         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2537                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2538         pSMB->MaxSetupCount = 4;
2539         pSMB->Reserved = 0;
2540         pSMB->ParameterOffset = 0;
2541         pSMB->DataCount = 0;
2542         pSMB->DataOffset = 0;
2543         pSMB->SetupCount = 4;
2544         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2545         pSMB->ParameterCount = pSMB->TotalParameterCount;
2546         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2547         pSMB->IsFsctl = 1; /* FSCTL */
2548         pSMB->IsRootFlag = 0;
2549         pSMB->Fid = fid; /* file handle always le */
2550         pSMB->ByteCount = 0;
2551
2552         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2553                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2554         if (rc) {
2555                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2556         } else {                /* decode response */
2557                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2558                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2559                 if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
2560                 /* BB also check enough total bytes returned */
2561                         rc = -EIO;      /* bad smb */
2562                         goto qreparse_out;
2563                 }
2564                 if (data_count && (data_count < 2048)) {
2565                         char *end_of_smb = 2 /* sizeof byte count */ +
2566                                 pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
2567
2568                         struct reparse_data *reparse_buf =
2569                                                 (struct reparse_data *)
2570                                                 ((char *)&pSMBr->hdr.Protocol
2571                                                                  + data_offset);
2572                         if ((char *)reparse_buf >= end_of_smb) {
2573                                 rc = -EIO;
2574                                 goto qreparse_out;
2575                         }
2576                         if ((reparse_buf->LinkNamesBuf +
2577                                 reparse_buf->TargetNameOffset +
2578                                 reparse_buf->TargetNameLen) > end_of_smb) {
2579                                 cFYI(1, ("reparse buf beyond SMB"));
2580                                 rc = -EIO;
2581                                 goto qreparse_out;
2582                         }
2583
2584                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2585                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
2586                                                 (reparse_buf->LinkNamesBuf +
2587                                                 reparse_buf->TargetNameOffset),
2588                                                 buflen,
2589                                                 reparse_buf->TargetNameLen,
2590                                                 nls_codepage, 0);
2591                         } else { /* ASCII names */
2592                                 strncpy(symlinkinfo,
2593                                         reparse_buf->LinkNamesBuf +
2594                                         reparse_buf->TargetNameOffset,
2595                                         min_t(const int, buflen,
2596                                            reparse_buf->TargetNameLen));
2597                         }
2598                 } else {
2599                         rc = -EIO;
2600                         cFYI(1, ("Invalid return data count on "
2601                                  "get reparse info ioctl"));
2602                 }
2603                 symlinkinfo[buflen] = 0; /* just in case so the caller
2604                                         does not go off the end of the buffer */
2605                 cFYI(1, ("readlink result - %s", symlinkinfo));
2606         }
2607
2608 qreparse_out:
2609         cifs_buf_release(pSMB);
2610
2611         /* Note: On -EAGAIN error only caller can retry on handle based calls
2612                 since file handle passed in no longer valid */
2613
2614         return rc;
2615 }
2616 #endif /* CIFS_EXPERIMENTAL */
2617
2618 #ifdef CONFIG_CIFS_POSIX
2619
2620 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2621 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2622                              struct cifs_posix_ace *cifs_ace)
2623 {
2624         /* u8 cifs fields do not need le conversion */
2625         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2626         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
2627         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2628         /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2629
2630         return;
2631 }
2632
2633 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2634 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2635                                const int acl_type, const int size_of_data_area)
2636 {
2637         int size =  0;
2638         int i;
2639         __u16 count;
2640         struct cifs_posix_ace *pACE;
2641         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2642         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2643
2644         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2645                 return -EOPNOTSUPP;
2646
2647         if (acl_type & ACL_TYPE_ACCESS) {
2648                 count = le16_to_cpu(cifs_acl->access_entry_count);
2649                 pACE = &cifs_acl->ace_array[0];
2650                 size = sizeof(struct cifs_posix_acl);
2651                 size += sizeof(struct cifs_posix_ace) * count;
2652                 /* check if we would go beyond end of SMB */
2653                 if (size_of_data_area < size) {
2654                         cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2655                                 size_of_data_area, size));
2656                         return -EINVAL;
2657                 }
2658         } else if (acl_type & ACL_TYPE_DEFAULT) {
2659                 count = le16_to_cpu(cifs_acl->access_entry_count);
2660                 size = sizeof(struct cifs_posix_acl);
2661                 size += sizeof(struct cifs_posix_ace) * count;
2662 /* skip past access ACEs to get to default ACEs */
2663                 pACE = &cifs_acl->ace_array[count];
2664                 count = le16_to_cpu(cifs_acl->default_entry_count);
2665                 size += sizeof(struct cifs_posix_ace) * count;
2666                 /* check if we would go beyond end of SMB */
2667                 if (size_of_data_area < size)
2668                         return -EINVAL;
2669         } else {
2670                 /* illegal type */
2671                 return -EINVAL;
2672         }
2673
2674         size = posix_acl_xattr_size(count);
2675         if ((buflen == 0) || (local_acl == NULL)) {
2676                 /* used to query ACL EA size */
2677         } else if (size > buflen) {
2678                 return -ERANGE;
2679         } else /* buffer big enough */ {
2680                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2681                 for (i = 0; i < count ; i++) {
2682                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
2683                         pACE++;
2684                 }
2685         }
2686         return size;
2687 }
2688
2689 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2690                                      const posix_acl_xattr_entry *local_ace)
2691 {
2692         __u16 rc = 0; /* 0 = ACL converted ok */
2693
2694         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2695         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
2696         /* BB is there a better way to handle the large uid? */
2697         if (local_ace->e_id == cpu_to_le32(-1)) {
2698         /* Probably no need to le convert -1 on any arch but can not hurt */
2699                 cifs_ace->cifs_uid = cpu_to_le64(-1);
2700         } else
2701                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2702         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2703         return rc;
2704 }
2705
2706 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2707 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2708                                const int buflen, const int acl_type)
2709 {
2710         __u16 rc = 0;
2711         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2712         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2713         int count;
2714         int i;
2715
2716         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2717                 return 0;
2718
2719         count = posix_acl_xattr_count((size_t)buflen);
2720         cFYI(1, ("setting acl with %d entries from buf of length %d and "
2721                 "version of %d",
2722                 count, buflen, le32_to_cpu(local_acl->a_version)));
2723         if (le32_to_cpu(local_acl->a_version) != 2) {
2724                 cFYI(1, ("unknown POSIX ACL version %d",
2725                      le32_to_cpu(local_acl->a_version)));
2726                 return 0;
2727         }
2728         cifs_acl->version = cpu_to_le16(1);
2729         if (acl_type == ACL_TYPE_ACCESS)
2730                 cifs_acl->access_entry_count = cpu_to_le16(count);
2731         else if (acl_type == ACL_TYPE_DEFAULT)
2732                 cifs_acl->default_entry_count = cpu_to_le16(count);
2733         else {
2734                 cFYI(1, ("unknown ACL type %d", acl_type));
2735                 return 0;
2736         }
2737         for (i = 0; i < count; i++) {
2738                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2739                                         &local_acl->a_entries[i]);
2740                 if (rc != 0) {
2741                         /* ACE not converted */
2742                         break;
2743                 }
2744         }
2745         if (rc == 0) {
2746                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2747                 rc += sizeof(struct cifs_posix_acl);
2748                 /* BB add check to make sure ACL does not overflow SMB */
2749         }
2750         return rc;
2751 }
2752
2753 int
2754 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2755                    const unsigned char *searchName,
2756                    char *acl_inf, const int buflen, const int acl_type,
2757                    const struct nls_table *nls_codepage, int remap)
2758 {
2759 /* SMB_QUERY_POSIX_ACL */
2760         TRANSACTION2_QPI_REQ *pSMB = NULL;
2761         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2762         int rc = 0;
2763         int bytes_returned;
2764         int name_len;
2765         __u16 params, byte_count;
2766
2767         cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2768
2769 queryAclRetry:
2770         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2771                 (void **) &pSMBr);
2772         if (rc)
2773                 return rc;
2774
2775         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2776                 name_len =
2777                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2778                                          PATH_MAX, nls_codepage, remap);
2779                 name_len++;     /* trailing null */
2780                 name_len *= 2;
2781                 pSMB->FileName[name_len] = 0;
2782                 pSMB->FileName[name_len+1] = 0;
2783         } else {        /* BB improve the check for buffer overruns BB */
2784                 name_len = strnlen(searchName, PATH_MAX);
2785                 name_len++;     /* trailing null */
2786                 strncpy(pSMB->FileName, searchName, name_len);
2787         }
2788
2789         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2790         pSMB->TotalDataCount = 0;
2791         pSMB->MaxParameterCount = cpu_to_le16(2);
2792         /* BB find exact max data count below from sess structure BB */
2793         pSMB->MaxDataCount = cpu_to_le16(4000);
2794         pSMB->MaxSetupCount = 0;
2795         pSMB->Reserved = 0;
2796         pSMB->Flags = 0;
2797         pSMB->Timeout = 0;
2798         pSMB->Reserved2 = 0;
2799         pSMB->ParameterOffset = cpu_to_le16(
2800                 offsetof(struct smb_com_transaction2_qpi_req,
2801                          InformationLevel) - 4);
2802         pSMB->DataCount = 0;
2803         pSMB->DataOffset = 0;
2804         pSMB->SetupCount = 1;
2805         pSMB->Reserved3 = 0;
2806         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2807         byte_count = params + 1 /* pad */ ;
2808         pSMB->TotalParameterCount = cpu_to_le16(params);
2809         pSMB->ParameterCount = pSMB->TotalParameterCount;
2810         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2811         pSMB->Reserved4 = 0;
2812         pSMB->hdr.smb_buf_length += byte_count;
2813         pSMB->ByteCount = cpu_to_le16(byte_count);
2814
2815         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2816                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2817         cifs_stats_inc(&tcon->num_acl_get);
2818         if (rc) {
2819                 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2820         } else {
2821                 /* decode response */
2822
2823                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2824                 if (rc || (pSMBr->ByteCount < 2))
2825                 /* BB also check enough total bytes returned */
2826                         rc = -EIO;      /* bad smb */
2827                 else {
2828                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2829                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2830                         rc = cifs_copy_posix_acl(acl_inf,
2831                                 (char *)&pSMBr->hdr.Protocol+data_offset,
2832                                 buflen, acl_type, count);
2833                 }
2834         }
2835         cifs_buf_release(pSMB);
2836         if (rc == -EAGAIN)
2837                 goto queryAclRetry;
2838         return rc;
2839 }
2840
2841 int
2842 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2843                    const unsigned char *fileName,
2844                    const char *local_acl, const int buflen,
2845                    const int acl_type,
2846                    const struct nls_table *nls_codepage, int remap)
2847 {
2848         struct smb_com_transaction2_spi_req *pSMB = NULL;
2849         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2850         char *parm_data;
2851         int name_len;
2852         int rc = 0;
2853         int bytes_returned = 0;
2854         __u16 params, byte_count, data_count, param_offset, offset;
2855
2856         cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2857 setAclRetry:
2858         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2859                       (void **) &pSMBr);
2860         if (rc)
2861                 return rc;
2862         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2863                 name_len =
2864                         cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2865                                       PATH_MAX, nls_codepage, remap);
2866                 name_len++;     /* trailing null */
2867                 name_len *= 2;
2868         } else {        /* BB improve the check for buffer overruns BB */
2869                 name_len = strnlen(fileName, PATH_MAX);
2870                 name_len++;     /* trailing null */
2871                 strncpy(pSMB->FileName, fileName, name_len);
2872         }
2873         params = 6 + name_len;
2874         pSMB->MaxParameterCount = cpu_to_le16(2);
2875         /* BB find max SMB size from sess */
2876         pSMB->MaxDataCount = cpu_to_le16(1000);
2877         pSMB->MaxSetupCount = 0;
2878         pSMB->Reserved = 0;
2879         pSMB->Flags = 0;
2880         pSMB->Timeout = 0;
2881         pSMB->Reserved2 = 0;
2882         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2883                                 InformationLevel) - 4;
2884         offset = param_offset + params;
2885         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2886         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2887
2888         /* convert to on the wire format for POSIX ACL */
2889         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2890
2891         if (data_count == 0) {
2892                 rc = -EOPNOTSUPP;
2893                 goto setACLerrorExit;
2894         }
2895         pSMB->DataOffset = cpu_to_le16(offset);
2896         pSMB->SetupCount = 1;
2897         pSMB->Reserved3 = 0;
2898         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2899         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2900         byte_count = 3 /* pad */  + params + data_count;
2901         pSMB->DataCount = cpu_to_le16(data_count);
2902         pSMB->TotalDataCount = pSMB->DataCount;
2903         pSMB->ParameterCount = cpu_to_le16(params);
2904         pSMB->TotalParameterCount = pSMB->ParameterCount;
2905         pSMB->Reserved4 = 0;
2906         pSMB->hdr.smb_buf_length += byte_count;
2907         pSMB->ByteCount = cpu_to_le16(byte_count);
2908         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2909                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2910         if (rc)
2911                 cFYI(1, ("Set POSIX ACL returned %d", rc));
2912
2913 setACLerrorExit:
2914         cifs_buf_release(pSMB);
2915         if (rc == -EAGAIN)
2916                 goto setAclRetry;
2917         return rc;
2918 }
2919
2920 /* BB fix tabs in this function FIXME BB */
2921 int
2922 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2923                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2924 {
2925         int rc = 0;
2926         struct smb_t2_qfi_req *pSMB = NULL;
2927         struct smb_t2_qfi_rsp *pSMBr = NULL;
2928         int bytes_returned;
2929         __u16 params, byte_count;
2930
2931         cFYI(1, ("In GetExtAttr"));
2932         if (tcon == NULL)
2933                 return -ENODEV;
2934
2935 GetExtAttrRetry:
2936         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2937                         (void **) &pSMBr);
2938         if (rc)
2939                 return rc;
2940
2941         params = 2 /* level */ + 2 /* fid */;
2942         pSMB->t2.TotalDataCount = 0;
2943         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2944         /* BB find exact max data count below from sess structure BB */
2945         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2946         pSMB->t2.MaxSetupCount = 0;
2947         pSMB->t2.Reserved = 0;
2948         pSMB->t2.Flags = 0;
2949         pSMB->t2.Timeout = 0;
2950         pSMB->t2.Reserved2 = 0;
2951         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2952                                                Fid) - 4);
2953         pSMB->t2.DataCount = 0;
2954         pSMB->t2.DataOffset = 0;
2955         pSMB->t2.SetupCount = 1;
2956         pSMB->t2.Reserved3 = 0;
2957         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2958         byte_count = params + 1 /* pad */ ;
2959         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2960         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2961         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2962         pSMB->Pad = 0;
2963         pSMB->Fid = netfid;
2964         pSMB->hdr.smb_buf_length += byte_count;
2965         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2966
2967         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2968                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2969         if (rc) {
2970                 cFYI(1, ("error %d in GetExtAttr", rc));
2971         } else {
2972                 /* decode response */
2973                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2974                 if (rc || (pSMBr->ByteCount < 2))
2975                 /* BB also check enough total bytes returned */
2976                         /* If rc should we check for EOPNOSUPP and
2977                            disable the srvino flag? or in caller? */
2978                         rc = -EIO;      /* bad smb */
2979                 else {
2980                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2981                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2982                         struct file_chattr_info *pfinfo;
2983                         /* BB Do we need a cast or hash here ? */
2984                         if (count != 16) {
2985                                 cFYI(1, ("Illegal size ret in GetExtAttr"));
2986                                 rc = -EIO;
2987                                 goto GetExtAttrOut;
2988                         }
2989                         pfinfo = (struct file_chattr_info *)
2990                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
2991                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2992                         *pMask = le64_to_cpu(pfinfo->mask);
2993                 }
2994         }
2995 GetExtAttrOut:
2996         cifs_buf_release(pSMB);
2997         if (rc == -EAGAIN)
2998                 goto GetExtAttrRetry;
2999         return rc;
3000 }
3001
3002 #endif /* CONFIG_POSIX */
3003
3004 #ifdef CONFIG_CIFS_EXPERIMENTAL
3005 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3006 int
3007 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3008                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3009 {
3010         int rc = 0;
3011         int buf_type = 0;
3012         QUERY_SEC_DESC_REQ *pSMB;
3013         struct kvec iov[1];
3014
3015         cFYI(1, ("GetCifsACL"));
3016
3017         *pbuflen = 0;
3018         *acl_inf = NULL;
3019
3020         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3021                         8 /* parm len */, tcon, (void **) &pSMB);
3022         if (rc)
3023                 return rc;
3024
3025         pSMB->MaxParameterCount = cpu_to_le32(4);
3026         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3027         pSMB->MaxSetupCount = 0;
3028         pSMB->Fid = fid; /* file handle always le */
3029         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3030                                      CIFS_ACL_DACL);
3031         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3032         pSMB->hdr.smb_buf_length += 11;
3033         iov[0].iov_base = (char *)pSMB;
3034         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3035
3036         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3037                          CIFS_STD_OP);
3038         cifs_stats_inc(&tcon->num_acl_get);
3039         if (rc) {
3040                 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3041         } else {                /* decode response */
3042                 __le32 *parm;
3043                 __u32 parm_len;
3044                 __u32 acl_len;
3045                 struct smb_com_ntransact_rsp *pSMBr;
3046                 char *pdata;
3047
3048 /* validate_nttransact */
3049                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3050                                         &pdata, &parm_len, pbuflen);
3051                 if (rc)
3052                         goto qsec_out;
3053                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3054
3055                 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3056
3057                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3058                         rc = -EIO;      /* bad smb */
3059                         *pbuflen = 0;
3060                         goto qsec_out;
3061                 }
3062
3063 /* BB check that data area is minimum length and as big as acl_len */
3064
3065                 acl_len = le32_to_cpu(*parm);
3066                 if (acl_len != *pbuflen) {
3067                         cERROR(1, ("acl length %d does not match %d",
3068                                    acl_len, *pbuflen));
3069                         if (*pbuflen > acl_len)
3070                                 *pbuflen = acl_len;
3071                 }
3072
3073                 /* check if buffer is big enough for the acl
3074                    header followed by the smallest SID */
3075                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3076                     (*pbuflen >= 64 * 1024)) {
3077                         cERROR(1, ("bad acl length %d", *pbuflen));
3078                         rc = -EINVAL;
3079                         *pbuflen = 0;
3080                 } else {
3081                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3082                         if (*acl_inf == NULL) {
3083                                 *pbuflen = 0;
3084                                 rc = -ENOMEM;
3085                         }
3086                         memcpy(*acl_inf, pdata, *pbuflen);
3087                 }
3088         }
3089 qsec_out:
3090         if (buf_type == CIFS_SMALL_BUFFER)
3091                 cifs_small_buf_release(iov[0].iov_base);
3092         else if (buf_type == CIFS_LARGE_BUFFER)
3093                 cifs_buf_release(iov[0].iov_base);
3094 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3095         return rc;
3096 }
3097
3098 int
3099 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3100                         struct cifs_ntsd *pntsd, __u32 acllen)
3101 {
3102         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3103         int rc = 0;
3104         int bytes_returned = 0;
3105         SET_SEC_DESC_REQ *pSMB = NULL;
3106         NTRANSACT_RSP *pSMBr = NULL;
3107
3108 setCifsAclRetry:
3109         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3110                         (void **) &pSMBr);
3111         if (rc)
3112                         return (rc);
3113
3114         pSMB->MaxSetupCount = 0;
3115         pSMB->Reserved = 0;
3116
3117         param_count = 8;
3118         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3119         data_count = acllen;
3120         data_offset = param_offset + param_count;
3121         byte_count = 3 /* pad */  + param_count;
3122
3123         pSMB->DataCount = cpu_to_le32(data_count);
3124         pSMB->TotalDataCount = pSMB->DataCount;
3125         pSMB->MaxParameterCount = cpu_to_le32(4);
3126         pSMB->MaxDataCount = cpu_to_le32(16384);
3127         pSMB->ParameterCount = cpu_to_le32(param_count);
3128         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3129         pSMB->TotalParameterCount = pSMB->ParameterCount;
3130         pSMB->DataOffset = cpu_to_le32(data_offset);
3131         pSMB->SetupCount = 0;
3132         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3133         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3134
3135         pSMB->Fid = fid; /* file handle always le */
3136         pSMB->Reserved2 = 0;
3137         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3138
3139         if (pntsd && acllen) {
3140                 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3141                         (char *) pntsd,
3142                         acllen);
3143                 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3144
3145         } else
3146                 pSMB->hdr.smb_buf_length += byte_count;
3147
3148         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3149                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3150
3151         cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3152         if (rc)
3153                 cFYI(1, ("Set CIFS ACL returned %d", rc));
3154         cifs_buf_release(pSMB);
3155
3156         if (rc == -EAGAIN)
3157                 goto setCifsAclRetry;
3158
3159         return (rc);
3160 }
3161
3162 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3163
3164 /* Legacy Query Path Information call for lookup to old servers such
3165    as Win9x/WinME */
3166 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3167                         const unsigned char *searchName,
3168                         FILE_ALL_INFO *pFinfo,
3169                         const struct nls_table *nls_codepage, int remap)
3170 {
3171         QUERY_INFORMATION_REQ *pSMB;
3172         QUERY_INFORMATION_RSP *pSMBr;
3173         int rc = 0;
3174         int bytes_returned;
3175         int name_len;
3176
3177         cFYI(1, ("In SMBQPath path %s", searchName));
3178 QInfRetry:
3179         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3180                       (void **) &pSMBr);
3181         if (rc)
3182                 return rc;
3183
3184         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3185                 name_len =
3186                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3187                                         PATH_MAX, nls_codepage, remap);
3188                 name_len++;     /* trailing null */
3189                 name_len *= 2;
3190         } else {
3191                 name_len = strnlen(searchName, PATH_MAX);
3192                 name_len++;     /* trailing null */
3193                 strncpy(pSMB->FileName, searchName, name_len);
3194         }
3195         pSMB->BufferFormat = 0x04;
3196         name_len++; /* account for buffer type byte */
3197         pSMB->hdr.smb_buf_length += (__u16) name_len;
3198         pSMB->ByteCount = cpu_to_le16(name_len);
3199
3200         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3201                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3202         if (rc) {
3203                 cFYI(1, ("Send error in QueryInfo = %d", rc));
3204         } else if (pFinfo) {
3205                 struct timespec ts;
3206                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3207
3208                 /* decode response */
3209                 /* BB FIXME - add time zone adjustment BB */
3210                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3211                 ts.tv_nsec = 0;
3212                 ts.tv_sec = time;
3213                 /* decode time fields */
3214                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3215                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3216                 pFinfo->LastAccessTime = 0;
3217                 pFinfo->AllocationSize =
3218                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3219                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3220                 pFinfo->Attributes =
3221                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3222         } else
3223                 rc = -EIO; /* bad buffer passed in */
3224