cifs: print error code if smb signature verification fails
[linux-3.10.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2010
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/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <asm/uaccess.h>
39 #include "cifspdu.h"
40 #include "cifsglob.h"
41 #include "cifsacl.h"
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
45 #include "fscache.h"
46
47 #ifdef CONFIG_CIFS_POSIX
48 static struct {
49         int index;
50         char *name;
51 } protocols[] = {
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53         {LANMAN_PROT, "\2LM1.2X002"},
54         {LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56         {CIFS_PROT, "\2NT LM 0.12"},
57         {POSIX_PROT, "\2POSIX 2"},
58         {BAD_PROT, "\2"}
59 };
60 #else
61 static struct {
62         int index;
63         char *name;
64 } protocols[] = {
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66         {LANMAN_PROT, "\2LM1.2X002"},
67         {LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69         {CIFS_PROT, "\2NT LM 0.12"},
70         {BAD_PROT, "\2"}
71 };
72 #endif
73
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
78 #else
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
81 #else /* not posix */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
84 #else
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
88
89 #ifdef CONFIG_HIGHMEM
90 /*
91  * On arches that have high memory, kmap address space is limited. By
92  * serializing the kmap operations on those arches, we ensure that we don't
93  * end up with a bunch of threads in writeback with partially mapped page
94  * arrays, stuck waiting for kmap to come back. That situation prevents
95  * progress and can deadlock.
96  */
97 static DEFINE_MUTEX(cifs_kmap_mutex);
98
99 static inline void
100 cifs_kmap_lock(void)
101 {
102         mutex_lock(&cifs_kmap_mutex);
103 }
104
105 static inline void
106 cifs_kmap_unlock(void)
107 {
108         mutex_unlock(&cifs_kmap_mutex);
109 }
110 #else /* !CONFIG_HIGHMEM */
111 #define cifs_kmap_lock() do { ; } while(0)
112 #define cifs_kmap_unlock() do { ; } while(0)
113 #endif /* CONFIG_HIGHMEM */
114
115 /*
116  * Mark as invalid, all open files on tree connections since they
117  * were closed when session to server was lost.
118  */
119 void
120 cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
121 {
122         struct cifsFileInfo *open_file = NULL;
123         struct list_head *tmp;
124         struct list_head *tmp1;
125
126         /* list all files open on tree connection and mark them invalid */
127         spin_lock(&cifs_file_list_lock);
128         list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
129                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
130                 open_file->invalidHandle = true;
131                 open_file->oplock_break_cancelled = true;
132         }
133         spin_unlock(&cifs_file_list_lock);
134         /*
135          * BB Add call to invalidate_inodes(sb) for all superblocks mounted
136          * to this tcon.
137          */
138 }
139
140 /* reconnect the socket, tcon, and smb session if needed */
141 static int
142 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
143 {
144         int rc;
145         struct cifs_ses *ses;
146         struct TCP_Server_Info *server;
147         struct nls_table *nls_codepage;
148
149         /*
150          * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
151          * tcp and smb session status done differently for those three - in the
152          * calling routine
153          */
154         if (!tcon)
155                 return 0;
156
157         ses = tcon->ses;
158         server = ses->server;
159
160         /*
161          * only tree disconnect, open, and write, (and ulogoff which does not
162          * have tcon) are allowed as we start force umount
163          */
164         if (tcon->tidStatus == CifsExiting) {
165                 if (smb_command != SMB_COM_WRITE_ANDX &&
166                     smb_command != SMB_COM_OPEN_ANDX &&
167                     smb_command != SMB_COM_TREE_DISCONNECT) {
168                         cFYI(1, "can not send cmd %d while umounting",
169                                 smb_command);
170                         return -ENODEV;
171                 }
172         }
173
174         /*
175          * Give demultiplex thread up to 10 seconds to reconnect, should be
176          * greater than cifs socket timeout which is 7 seconds
177          */
178         while (server->tcpStatus == CifsNeedReconnect) {
179                 wait_event_interruptible_timeout(server->response_q,
180                         (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
181
182                 /* are we still trying to reconnect? */
183                 if (server->tcpStatus != CifsNeedReconnect)
184                         break;
185
186                 /*
187                  * on "soft" mounts we wait once. Hard mounts keep
188                  * retrying until process is killed or server comes
189                  * back on-line
190                  */
191                 if (!tcon->retry) {
192                         cFYI(1, "gave up waiting on reconnect in smb_init");
193                         return -EHOSTDOWN;
194                 }
195         }
196
197         if (!ses->need_reconnect && !tcon->need_reconnect)
198                 return 0;
199
200         nls_codepage = load_nls_default();
201
202         /*
203          * need to prevent multiple threads trying to simultaneously
204          * reconnect the same SMB session
205          */
206         mutex_lock(&ses->session_mutex);
207         rc = cifs_negotiate_protocol(0, ses);
208         if (rc == 0 && ses->need_reconnect)
209                 rc = cifs_setup_session(0, ses, nls_codepage);
210
211         /* do we need to reconnect tcon? */
212         if (rc || !tcon->need_reconnect) {
213                 mutex_unlock(&ses->session_mutex);
214                 goto out;
215         }
216
217         cifs_mark_open_files_invalid(tcon);
218         rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
219         mutex_unlock(&ses->session_mutex);
220         cFYI(1, "reconnect tcon rc = %d", rc);
221
222         if (rc)
223                 goto out;
224
225         /*
226          * FIXME: check if wsize needs updated due to negotiated smb buffer
227          *        size shrinking
228          */
229         atomic_inc(&tconInfoReconnectCount);
230
231         /* tell server Unix caps we support */
232         if (ses->capabilities & CAP_UNIX)
233                 reset_cifs_unix_caps(0, tcon, NULL, NULL);
234
235         /*
236          * Removed call to reopen open files here. It is safer (and faster) to
237          * reopen files one at a time as needed in read and write.
238          *
239          * FIXME: what about file locks? don't we need to reclaim them ASAP?
240          */
241
242 out:
243         /*
244          * Check if handle based operation so we know whether we can continue
245          * or not without returning to caller to reset file handle
246          */
247         switch (smb_command) {
248         case SMB_COM_READ_ANDX:
249         case SMB_COM_WRITE_ANDX:
250         case SMB_COM_CLOSE:
251         case SMB_COM_FIND_CLOSE2:
252         case SMB_COM_LOCKING_ANDX:
253                 rc = -EAGAIN;
254         }
255
256         unload_nls(nls_codepage);
257         return rc;
258 }
259
260 /* Allocate and return pointer to an SMB request buffer, and set basic
261    SMB information in the SMB header.  If the return code is zero, this
262    function must have filled in request_buf pointer */
263 static int
264 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
265                 void **request_buf)
266 {
267         int rc;
268
269         rc = cifs_reconnect_tcon(tcon, smb_command);
270         if (rc)
271                 return rc;
272
273         *request_buf = cifs_small_buf_get();
274         if (*request_buf == NULL) {
275                 /* BB should we add a retry in here if not a writepage? */
276                 return -ENOMEM;
277         }
278
279         header_assemble((struct smb_hdr *) *request_buf, smb_command,
280                         tcon, wct);
281
282         if (tcon != NULL)
283                 cifs_stats_inc(&tcon->num_smbs_sent);
284
285         return 0;
286 }
287
288 int
289 small_smb_init_no_tc(const int smb_command, const int wct,
290                      struct cifs_ses *ses, void **request_buf)
291 {
292         int rc;
293         struct smb_hdr *buffer;
294
295         rc = small_smb_init(smb_command, wct, NULL, request_buf);
296         if (rc)
297                 return rc;
298
299         buffer = (struct smb_hdr *)*request_buf;
300         buffer->Mid = get_next_mid(ses->server);
301         if (ses->capabilities & CAP_UNICODE)
302                 buffer->Flags2 |= SMBFLG2_UNICODE;
303         if (ses->capabilities & CAP_STATUS32)
304                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
305
306         /* uid, tid can stay at zero as set in header assemble */
307
308         /* BB add support for turning on the signing when
309         this function is used after 1st of session setup requests */
310
311         return rc;
312 }
313
314 /* If the return code is zero, this function must fill in request_buf pointer */
315 static int
316 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
317                         void **request_buf, void **response_buf)
318 {
319         *request_buf = cifs_buf_get();
320         if (*request_buf == NULL) {
321                 /* BB should we add a retry in here if not a writepage? */
322                 return -ENOMEM;
323         }
324     /* Although the original thought was we needed the response buf for  */
325     /* potential retries of smb operations it turns out we can determine */
326     /* from the mid flags when the request buffer can be resent without  */
327     /* having to use a second distinct buffer for the response */
328         if (response_buf)
329                 *response_buf = *request_buf;
330
331         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
332                         wct);
333
334         if (tcon != NULL)
335                 cifs_stats_inc(&tcon->num_smbs_sent);
336
337         return 0;
338 }
339
340 /* If the return code is zero, this function must fill in request_buf pointer */
341 static int
342 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
343          void **request_buf, void **response_buf)
344 {
345         int rc;
346
347         rc = cifs_reconnect_tcon(tcon, smb_command);
348         if (rc)
349                 return rc;
350
351         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
352 }
353
354 static int
355 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
356                         void **request_buf, void **response_buf)
357 {
358         if (tcon->ses->need_reconnect || tcon->need_reconnect)
359                 return -EHOSTDOWN;
360
361         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
362 }
363
364 static int validate_t2(struct smb_t2_rsp *pSMB)
365 {
366         unsigned int total_size;
367
368         /* check for plausible wct */
369         if (pSMB->hdr.WordCount < 10)
370                 goto vt2_err;
371
372         /* check for parm and data offset going beyond end of smb */
373         if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
374             get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
375                 goto vt2_err;
376
377         total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
378         if (total_size >= 512)
379                 goto vt2_err;
380
381         /* check that bcc is at least as big as parms + data, and that it is
382          * less than negotiated smb buffer
383          */
384         total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
385         if (total_size > get_bcc(&pSMB->hdr) ||
386             total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
387                 goto vt2_err;
388
389         return 0;
390 vt2_err:
391         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
392                 sizeof(struct smb_t2_rsp) + 16);
393         return -EINVAL;
394 }
395
396 int
397 CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
398 {
399         NEGOTIATE_REQ *pSMB;
400         NEGOTIATE_RSP *pSMBr;
401         int rc = 0;
402         int bytes_returned;
403         int i;
404         struct TCP_Server_Info *server;
405         u16 count;
406         unsigned int secFlags;
407
408         if (ses->server)
409                 server = ses->server;
410         else {
411                 rc = -EIO;
412                 return rc;
413         }
414         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
415                       (void **) &pSMB, (void **) &pSMBr);
416         if (rc)
417                 return rc;
418
419         /* if any of auth flags (ie not sign or seal) are overriden use them */
420         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
421                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
422         else /* if override flags set only sign/seal OR them with global auth */
423                 secFlags = global_secflags | ses->overrideSecFlg;
424
425         cFYI(1, "secFlags 0x%x", secFlags);
426
427         pSMB->hdr.Mid = get_next_mid(server);
428         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
429
430         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
431                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
432         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
433                 cFYI(1, "Kerberos only mechanism, enable extended security");
434                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
435         } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
436                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
437         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
438                 cFYI(1, "NTLMSSP only mechanism, enable extended security");
439                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
440         }
441
442         count = 0;
443         for (i = 0; i < CIFS_NUM_PROT; i++) {
444                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
445                 count += strlen(protocols[i].name) + 1;
446                 /* null at end of source and target buffers anyway */
447         }
448         inc_rfc1001_len(pSMB, count);
449         pSMB->ByteCount = cpu_to_le16(count);
450
451         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
452                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
453         if (rc != 0)
454                 goto neg_err_exit;
455
456         server->dialect = le16_to_cpu(pSMBr->DialectIndex);
457         cFYI(1, "Dialect: %d", server->dialect);
458         /* Check wct = 1 error case */
459         if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
460                 /* core returns wct = 1, but we do not ask for core - otherwise
461                 small wct just comes when dialect index is -1 indicating we
462                 could not negotiate a common dialect */
463                 rc = -EOPNOTSUPP;
464                 goto neg_err_exit;
465 #ifdef CONFIG_CIFS_WEAK_PW_HASH
466         } else if ((pSMBr->hdr.WordCount == 13)
467                         && ((server->dialect == LANMAN_PROT)
468                                 || (server->dialect == LANMAN2_PROT))) {
469                 __s16 tmp;
470                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
471
472                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
473                         (secFlags & CIFSSEC_MAY_PLNTXT))
474                         server->secType = LANMAN;
475                 else {
476                         cERROR(1, "mount failed weak security disabled"
477                                    " in /proc/fs/cifs/SecurityFlags");
478                         rc = -EOPNOTSUPP;
479                         goto neg_err_exit;
480                 }
481                 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
482                 server->maxReq = min_t(unsigned int,
483                                        le16_to_cpu(rsp->MaxMpxCount),
484                                        cifs_max_pending);
485                 set_credits(server, server->maxReq);
486                 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
487                 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
488                 /* even though we do not use raw we might as well set this
489                 accurately, in case we ever find a need for it */
490                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
491                         server->max_rw = 0xFF00;
492                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
493                 } else {
494                         server->max_rw = 0;/* do not need to use raw anyway */
495                         server->capabilities = CAP_MPX_MODE;
496                 }
497                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
498                 if (tmp == -1) {
499                         /* OS/2 often does not set timezone therefore
500                          * we must use server time to calc time zone.
501                          * Could deviate slightly from the right zone.
502                          * Smallest defined timezone difference is 15 minutes
503                          * (i.e. Nepal).  Rounding up/down is done to match
504                          * this requirement.
505                          */
506                         int val, seconds, remain, result;
507                         struct timespec ts, utc;
508                         utc = CURRENT_TIME;
509                         ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
510                                             rsp->SrvTime.Time, 0);
511                         cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
512                                 (int)ts.tv_sec, (int)utc.tv_sec,
513                                 (int)(utc.tv_sec - ts.tv_sec));
514                         val = (int)(utc.tv_sec - ts.tv_sec);
515                         seconds = abs(val);
516                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
517                         remain = seconds % MIN_TZ_ADJ;
518                         if (remain >= (MIN_TZ_ADJ / 2))
519                                 result += MIN_TZ_ADJ;
520                         if (val < 0)
521                                 result = -result;
522                         server->timeAdj = result;
523                 } else {
524                         server->timeAdj = (int)tmp;
525                         server->timeAdj *= 60; /* also in seconds */
526                 }
527                 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
528
529
530                 /* BB get server time for time conversions and add
531                 code to use it and timezone since this is not UTC */
532
533                 if (rsp->EncryptionKeyLength ==
534                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
535                         memcpy(ses->server->cryptkey, rsp->EncryptionKey,
536                                 CIFS_CRYPTO_KEY_SIZE);
537                 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
538                         rc = -EIO; /* need cryptkey unless plain text */
539                         goto neg_err_exit;
540                 }
541
542                 cFYI(1, "LANMAN negotiated");
543                 /* we will not end up setting signing flags - as no signing
544                 was in LANMAN and server did not return the flags on */
545                 goto signing_check;
546 #else /* weak security disabled */
547         } else if (pSMBr->hdr.WordCount == 13) {
548                 cERROR(1, "mount failed, cifs module not built "
549                           "with CIFS_WEAK_PW_HASH support");
550                 rc = -EOPNOTSUPP;
551 #endif /* WEAK_PW_HASH */
552                 goto neg_err_exit;
553         } else if (pSMBr->hdr.WordCount != 17) {
554                 /* unknown wct */
555                 rc = -EOPNOTSUPP;
556                 goto neg_err_exit;
557         }
558         /* else wct == 17 NTLM */
559         server->sec_mode = pSMBr->SecurityMode;
560         if ((server->sec_mode & SECMODE_USER) == 0)
561                 cFYI(1, "share mode security");
562
563         if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
564 #ifdef CONFIG_CIFS_WEAK_PW_HASH
565                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
566 #endif /* CIFS_WEAK_PW_HASH */
567                         cERROR(1, "Server requests plain text password"
568                                   " but client support disabled");
569
570         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
571                 server->secType = NTLMv2;
572         else if (secFlags & CIFSSEC_MAY_NTLM)
573                 server->secType = NTLM;
574         else if (secFlags & CIFSSEC_MAY_NTLMV2)
575                 server->secType = NTLMv2;
576         else if (secFlags & CIFSSEC_MAY_KRB5)
577                 server->secType = Kerberos;
578         else if (secFlags & CIFSSEC_MAY_NTLMSSP)
579                 server->secType = RawNTLMSSP;
580         else if (secFlags & CIFSSEC_MAY_LANMAN)
581                 server->secType = LANMAN;
582         else {
583                 rc = -EOPNOTSUPP;
584                 cERROR(1, "Invalid security type");
585                 goto neg_err_exit;
586         }
587         /* else ... any others ...? */
588
589         /* one byte, so no need to convert this or EncryptionKeyLen from
590            little endian */
591         server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
592                                cifs_max_pending);
593         set_credits(server, server->maxReq);
594         /* probably no need to store and check maxvcs */
595         server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
596         server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
597         cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
598         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
599         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
600         server->timeAdj *= 60;
601         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
602                 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
603                        CIFS_CRYPTO_KEY_SIZE);
604         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
605                         server->capabilities & CAP_EXTENDED_SECURITY) &&
606                                 (pSMBr->EncryptionKeyLength == 0)) {
607                 /* decode security blob */
608                 count = get_bcc(&pSMBr->hdr);
609                 if (count < 16) {
610                         rc = -EIO;
611                         goto neg_err_exit;
612                 }
613                 spin_lock(&cifs_tcp_ses_lock);
614                 if (server->srv_count > 1) {
615                         spin_unlock(&cifs_tcp_ses_lock);
616                         if (memcmp(server->server_GUID,
617                                    pSMBr->u.extended_response.
618                                    GUID, 16) != 0) {
619                                 cFYI(1, "server UID changed");
620                                 memcpy(server->server_GUID,
621                                         pSMBr->u.extended_response.GUID,
622                                         16);
623                         }
624                 } else {
625                         spin_unlock(&cifs_tcp_ses_lock);
626                         memcpy(server->server_GUID,
627                                pSMBr->u.extended_response.GUID, 16);
628                 }
629
630                 if (count == 16) {
631                         server->secType = RawNTLMSSP;
632                 } else {
633                         rc = decode_negTokenInit(pSMBr->u.extended_response.
634                                                  SecurityBlob, count - 16,
635                                                  server);
636                         if (rc == 1)
637                                 rc = 0;
638                         else
639                                 rc = -EINVAL;
640                         if (server->secType == Kerberos) {
641                                 if (!server->sec_kerberos &&
642                                                 !server->sec_mskerberos)
643                                         rc = -EOPNOTSUPP;
644                         } else if (server->secType == RawNTLMSSP) {
645                                 if (!server->sec_ntlmssp)
646                                         rc = -EOPNOTSUPP;
647                         } else
648                                         rc = -EOPNOTSUPP;
649                 }
650         } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
651                 rc = -EIO; /* no crypt key only if plain text pwd */
652                 goto neg_err_exit;
653         } else
654                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
655
656 #ifdef CONFIG_CIFS_WEAK_PW_HASH
657 signing_check:
658 #endif
659         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
660                 /* MUST_SIGN already includes the MAY_SIGN FLAG
661                    so if this is zero it means that signing is disabled */
662                 cFYI(1, "Signing disabled");
663                 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
664                         cERROR(1, "Server requires "
665                                    "packet signing to be enabled in "
666                                    "/proc/fs/cifs/SecurityFlags.");
667                         rc = -EOPNOTSUPP;
668                 }
669                 server->sec_mode &=
670                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
671         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
672                 /* signing required */
673                 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
674                 if ((server->sec_mode &
675                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
676                         cERROR(1, "signing required but server lacks support");
677                         rc = -EOPNOTSUPP;
678                 } else
679                         server->sec_mode |= SECMODE_SIGN_REQUIRED;
680         } else {
681                 /* signing optional ie CIFSSEC_MAY_SIGN */
682                 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
683                         server->sec_mode &=
684                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
685         }
686
687 neg_err_exit:
688         cifs_buf_release(pSMB);
689
690         cFYI(1, "negprot rc %d", rc);
691         return rc;
692 }
693
694 int
695 CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
696 {
697         struct smb_hdr *smb_buffer;
698         int rc = 0;
699
700         cFYI(1, "In tree disconnect");
701
702         /* BB: do we need to check this? These should never be NULL. */
703         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
704                 return -EIO;
705
706         /*
707          * No need to return error on this operation if tid invalidated and
708          * closed on server already e.g. due to tcp session crashing. Also,
709          * the tcon is no longer on the list, so no need to take lock before
710          * checking this.
711          */
712         if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
713                 return 0;
714
715         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
716                             (void **)&smb_buffer);
717         if (rc)
718                 return rc;
719
720         rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
721         if (rc)
722                 cFYI(1, "Tree disconnect failed %d", rc);
723
724         /* No need to return error on this operation if tid invalidated and
725            closed on server already e.g. due to tcp session crashing */
726         if (rc == -EAGAIN)
727                 rc = 0;
728
729         return rc;
730 }
731
732 /*
733  * This is a no-op for now. We're not really interested in the reply, but
734  * rather in the fact that the server sent one and that server->lstrp
735  * gets updated.
736  *
737  * FIXME: maybe we should consider checking that the reply matches request?
738  */
739 static void
740 cifs_echo_callback(struct mid_q_entry *mid)
741 {
742         struct TCP_Server_Info *server = mid->callback_data;
743
744         DeleteMidQEntry(mid);
745         add_credits(server, 1, CIFS_ECHO_OP);
746 }
747
748 int
749 CIFSSMBEcho(struct TCP_Server_Info *server)
750 {
751         ECHO_REQ *smb;
752         int rc = 0;
753         struct kvec iov;
754
755         cFYI(1, "In echo request");
756
757         rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
758         if (rc)
759                 return rc;
760
761         /* set up echo request */
762         smb->hdr.Tid = 0xffff;
763         smb->hdr.WordCount = 1;
764         put_unaligned_le16(1, &smb->EchoCount);
765         put_bcc(1, &smb->hdr);
766         smb->Data[0] = 'a';
767         inc_rfc1001_len(smb, 3);
768         iov.iov_base = smb;
769         iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
770
771         rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
772                              server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
773         if (rc)
774                 cFYI(1, "Echo request failed: %d", rc);
775
776         cifs_small_buf_release(smb);
777
778         return rc;
779 }
780
781 int
782 CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
783 {
784         LOGOFF_ANDX_REQ *pSMB;
785         int rc = 0;
786
787         cFYI(1, "In SMBLogoff for session disconnect");
788
789         /*
790          * BB: do we need to check validity of ses and server? They should
791          * always be valid since we have an active reference. If not, that
792          * should probably be a BUG()
793          */
794         if (!ses || !ses->server)
795                 return -EIO;
796
797         mutex_lock(&ses->session_mutex);
798         if (ses->need_reconnect)
799                 goto session_already_dead; /* no need to send SMBlogoff if uid
800                                               already closed due to reconnect */
801         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
802         if (rc) {
803                 mutex_unlock(&ses->session_mutex);
804                 return rc;
805         }
806
807         pSMB->hdr.Mid = get_next_mid(ses->server);
808
809         if (ses->server->sec_mode &
810                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
811                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
812
813         pSMB->hdr.Uid = ses->Suid;
814
815         pSMB->AndXCommand = 0xFF;
816         rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
817 session_already_dead:
818         mutex_unlock(&ses->session_mutex);
819
820         /* if session dead then we do not need to do ulogoff,
821                 since server closed smb session, no sense reporting
822                 error */
823         if (rc == -EAGAIN)
824                 rc = 0;
825         return rc;
826 }
827
828 int
829 CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
830                  const char *fileName, __u16 type,
831                  const struct nls_table *nls_codepage, int remap)
832 {
833         TRANSACTION2_SPI_REQ *pSMB = NULL;
834         TRANSACTION2_SPI_RSP *pSMBr = NULL;
835         struct unlink_psx_rq *pRqD;
836         int name_len;
837         int rc = 0;
838         int bytes_returned = 0;
839         __u16 params, param_offset, offset, byte_count;
840
841         cFYI(1, "In POSIX delete");
842 PsxDelete:
843         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
844                       (void **) &pSMBr);
845         if (rc)
846                 return rc;
847
848         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
849                 name_len =
850                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
851                                        PATH_MAX, nls_codepage, remap);
852                 name_len++;     /* trailing null */
853                 name_len *= 2;
854         } else { /* BB add path length overrun check */
855                 name_len = strnlen(fileName, PATH_MAX);
856                 name_len++;     /* trailing null */
857                 strncpy(pSMB->FileName, fileName, name_len);
858         }
859
860         params = 6 + name_len;
861         pSMB->MaxParameterCount = cpu_to_le16(2);
862         pSMB->MaxDataCount = 0; /* BB double check this with jra */
863         pSMB->MaxSetupCount = 0;
864         pSMB->Reserved = 0;
865         pSMB->Flags = 0;
866         pSMB->Timeout = 0;
867         pSMB->Reserved2 = 0;
868         param_offset = offsetof(struct smb_com_transaction2_spi_req,
869                                 InformationLevel) - 4;
870         offset = param_offset + params;
871
872         /* Setup pointer to Request Data (inode type) */
873         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
874         pRqD->type = cpu_to_le16(type);
875         pSMB->ParameterOffset = cpu_to_le16(param_offset);
876         pSMB->DataOffset = cpu_to_le16(offset);
877         pSMB->SetupCount = 1;
878         pSMB->Reserved3 = 0;
879         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
880         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
881
882         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
883         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
884         pSMB->ParameterCount = cpu_to_le16(params);
885         pSMB->TotalParameterCount = pSMB->ParameterCount;
886         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
887         pSMB->Reserved4 = 0;
888         inc_rfc1001_len(pSMB, byte_count);
889         pSMB->ByteCount = cpu_to_le16(byte_count);
890         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
891                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
892         if (rc)
893                 cFYI(1, "Posix delete returned %d", rc);
894         cifs_buf_release(pSMB);
895
896         cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
897
898         if (rc == -EAGAIN)
899                 goto PsxDelete;
900
901         return rc;
902 }
903
904 int
905 CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
906                const char *fileName, const struct nls_table *nls_codepage,
907                int remap)
908 {
909         DELETE_FILE_REQ *pSMB = NULL;
910         DELETE_FILE_RSP *pSMBr = NULL;
911         int rc = 0;
912         int bytes_returned;
913         int name_len;
914
915 DelFileRetry:
916         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
917                       (void **) &pSMBr);
918         if (rc)
919                 return rc;
920
921         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
922                 name_len =
923                     cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
924                                        PATH_MAX, nls_codepage, remap);
925                 name_len++;     /* trailing null */
926                 name_len *= 2;
927         } else {                /* BB improve check for buffer overruns BB */
928                 name_len = strnlen(fileName, PATH_MAX);
929                 name_len++;     /* trailing null */
930                 strncpy(pSMB->fileName, fileName, name_len);
931         }
932         pSMB->SearchAttributes =
933             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
934         pSMB->BufferFormat = 0x04;
935         inc_rfc1001_len(pSMB, name_len + 1);
936         pSMB->ByteCount = cpu_to_le16(name_len + 1);
937         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
938                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
939         cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
940         if (rc)
941                 cFYI(1, "Error in RMFile = %d", rc);
942
943         cifs_buf_release(pSMB);
944         if (rc == -EAGAIN)
945                 goto DelFileRetry;
946
947         return rc;
948 }
949
950 int
951 CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
952              struct cifs_sb_info *cifs_sb)
953 {
954         DELETE_DIRECTORY_REQ *pSMB = NULL;
955         DELETE_DIRECTORY_RSP *pSMBr = NULL;
956         int rc = 0;
957         int bytes_returned;
958         int name_len;
959         int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
960
961         cFYI(1, "In CIFSSMBRmDir");
962 RmDirRetry:
963         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
964                       (void **) &pSMBr);
965         if (rc)
966                 return rc;
967
968         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
969                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
970                                               PATH_MAX, cifs_sb->local_nls,
971                                               remap);
972                 name_len++;     /* trailing null */
973                 name_len *= 2;
974         } else {                /* BB improve check for buffer overruns BB */
975                 name_len = strnlen(name, PATH_MAX);
976                 name_len++;     /* trailing null */
977                 strncpy(pSMB->DirName, name, name_len);
978         }
979
980         pSMB->BufferFormat = 0x04;
981         inc_rfc1001_len(pSMB, name_len + 1);
982         pSMB->ByteCount = cpu_to_le16(name_len + 1);
983         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
984                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
985         cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
986         if (rc)
987                 cFYI(1, "Error in RMDir = %d", rc);
988
989         cifs_buf_release(pSMB);
990         if (rc == -EAGAIN)
991                 goto RmDirRetry;
992         return rc;
993 }
994
995 int
996 CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
997              struct cifs_sb_info *cifs_sb)
998 {
999         int rc = 0;
1000         CREATE_DIRECTORY_REQ *pSMB = NULL;
1001         CREATE_DIRECTORY_RSP *pSMBr = NULL;
1002         int bytes_returned;
1003         int name_len;
1004         int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
1005
1006         cFYI(1, "In CIFSSMBMkDir");
1007 MkDirRetry:
1008         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1009                       (void **) &pSMBr);
1010         if (rc)
1011                 return rc;
1012
1013         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1014                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1015                                               PATH_MAX, cifs_sb->local_nls,
1016                                               remap);
1017                 name_len++;     /* trailing null */
1018                 name_len *= 2;
1019         } else {                /* BB improve check for buffer overruns BB */
1020                 name_len = strnlen(name, PATH_MAX);
1021                 name_len++;     /* trailing null */
1022                 strncpy(pSMB->DirName, name, name_len);
1023         }
1024
1025         pSMB->BufferFormat = 0x04;
1026         inc_rfc1001_len(pSMB, name_len + 1);
1027         pSMB->ByteCount = cpu_to_le16(name_len + 1);
1028         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1029                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1030         cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
1031         if (rc)
1032                 cFYI(1, "Error in Mkdir = %d", rc);
1033
1034         cifs_buf_release(pSMB);
1035         if (rc == -EAGAIN)
1036                 goto MkDirRetry;
1037         return rc;
1038 }
1039
1040 int
1041 CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1042                 __u32 posix_flags, __u64 mode, __u16 *netfid,
1043                 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1044                 const char *name, const struct nls_table *nls_codepage,
1045                 int remap)
1046 {
1047         TRANSACTION2_SPI_REQ *pSMB = NULL;
1048         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1049         int name_len;
1050         int rc = 0;
1051         int bytes_returned = 0;
1052         __u16 params, param_offset, offset, byte_count, count;
1053         OPEN_PSX_REQ *pdata;
1054         OPEN_PSX_RSP *psx_rsp;
1055
1056         cFYI(1, "In POSIX Create");
1057 PsxCreat:
1058         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1059                       (void **) &pSMBr);
1060         if (rc)
1061                 return rc;
1062
1063         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1064                 name_len =
1065                     cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1066                                        PATH_MAX, nls_codepage, remap);
1067                 name_len++;     /* trailing null */
1068                 name_len *= 2;
1069         } else {        /* BB improve the check for buffer overruns BB */
1070                 name_len = strnlen(name, PATH_MAX);
1071                 name_len++;     /* trailing null */
1072                 strncpy(pSMB->FileName, name, name_len);
1073         }
1074
1075         params = 6 + name_len;
1076         count = sizeof(OPEN_PSX_REQ);
1077         pSMB->MaxParameterCount = cpu_to_le16(2);
1078         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1079         pSMB->MaxSetupCount = 0;
1080         pSMB->Reserved = 0;
1081         pSMB->Flags = 0;
1082         pSMB->Timeout = 0;
1083         pSMB->Reserved2 = 0;
1084         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1085                                 InformationLevel) - 4;
1086         offset = param_offset + params;
1087         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1088         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1089         pdata->Permissions = cpu_to_le64(mode);
1090         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1091         pdata->OpenFlags =  cpu_to_le32(*pOplock);
1092         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1093         pSMB->DataOffset = cpu_to_le16(offset);
1094         pSMB->SetupCount = 1;
1095         pSMB->Reserved3 = 0;
1096         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1097         byte_count = 3 /* pad */  + params + count;
1098
1099         pSMB->DataCount = cpu_to_le16(count);
1100         pSMB->ParameterCount = cpu_to_le16(params);
1101         pSMB->TotalDataCount = pSMB->DataCount;
1102         pSMB->TotalParameterCount = pSMB->ParameterCount;
1103         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1104         pSMB->Reserved4 = 0;
1105         inc_rfc1001_len(pSMB, byte_count);
1106         pSMB->ByteCount = cpu_to_le16(byte_count);
1107         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1108                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1109         if (rc) {
1110                 cFYI(1, "Posix create returned %d", rc);
1111                 goto psx_create_err;
1112         }
1113
1114         cFYI(1, "copying inode info");
1115         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1116
1117         if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1118                 rc = -EIO;      /* bad smb */
1119                 goto psx_create_err;
1120         }
1121
1122         /* copy return information to pRetData */
1123         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1124                         + le16_to_cpu(pSMBr->t2.DataOffset));
1125
1126         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1127         if (netfid)
1128                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1129         /* Let caller know file was created so we can set the mode. */
1130         /* Do we care about the CreateAction in any other cases? */
1131         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1132                 *pOplock |= CIFS_CREATE_ACTION;
1133         /* check to make sure response data is there */
1134         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1135                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1136                 cFYI(DBG2, "unknown type");
1137         } else {
1138                 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1139                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1140                         cERROR(1, "Open response data too small");
1141                         pRetData->Type = cpu_to_le32(-1);
1142                         goto psx_create_err;
1143                 }
1144                 memcpy((char *) pRetData,
1145                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1146                         sizeof(FILE_UNIX_BASIC_INFO));
1147         }
1148
1149 psx_create_err:
1150         cifs_buf_release(pSMB);
1151
1152         if (posix_flags & SMB_O_DIRECTORY)
1153                 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1154         else
1155                 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1156
1157         if (rc == -EAGAIN)
1158                 goto PsxCreat;
1159
1160         return rc;
1161 }
1162
1163 static __u16 convert_disposition(int disposition)
1164 {
1165         __u16 ofun = 0;
1166
1167         switch (disposition) {
1168                 case FILE_SUPERSEDE:
1169                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1170                         break;
1171                 case FILE_OPEN:
1172                         ofun = SMBOPEN_OAPPEND;
1173                         break;
1174                 case FILE_CREATE:
1175                         ofun = SMBOPEN_OCREATE;
1176                         break;
1177                 case FILE_OPEN_IF:
1178                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1179                         break;
1180                 case FILE_OVERWRITE:
1181                         ofun = SMBOPEN_OTRUNC;
1182                         break;
1183                 case FILE_OVERWRITE_IF:
1184                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1185                         break;
1186                 default:
1187                         cFYI(1, "unknown disposition %d", disposition);
1188                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1189         }
1190         return ofun;
1191 }
1192
1193 static int
1194 access_flags_to_smbopen_mode(const int access_flags)
1195 {
1196         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1197
1198         if (masked_flags == GENERIC_READ)
1199                 return SMBOPEN_READ;
1200         else if (masked_flags == GENERIC_WRITE)
1201                 return SMBOPEN_WRITE;
1202
1203         /* just go for read/write */
1204         return SMBOPEN_READWRITE;
1205 }
1206
1207 int
1208 SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1209             const char *fileName, const int openDisposition,
1210             const int access_flags, const int create_options, __u16 *netfid,
1211             int *pOplock, FILE_ALL_INFO *pfile_info,
1212             const struct nls_table *nls_codepage, int remap)
1213 {
1214         int rc = -EACCES;
1215         OPENX_REQ *pSMB = NULL;
1216         OPENX_RSP *pSMBr = NULL;
1217         int bytes_returned;
1218         int name_len;
1219         __u16 count;
1220
1221 OldOpenRetry:
1222         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1223                       (void **) &pSMBr);
1224         if (rc)
1225                 return rc;
1226
1227         pSMB->AndXCommand = 0xFF;       /* none */
1228
1229         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1230                 count = 1;      /* account for one byte pad to word boundary */
1231                 name_len =
1232                    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1233                                       fileName, PATH_MAX, nls_codepage, remap);
1234                 name_len++;     /* trailing null */
1235                 name_len *= 2;
1236         } else {                /* BB improve check for buffer overruns BB */
1237                 count = 0;      /* no pad */
1238                 name_len = strnlen(fileName, PATH_MAX);
1239                 name_len++;     /* trailing null */
1240                 strncpy(pSMB->fileName, fileName, name_len);
1241         }
1242         if (*pOplock & REQ_OPLOCK)
1243                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1244         else if (*pOplock & REQ_BATCHOPLOCK)
1245                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1246
1247         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1248         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1249         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1250         /* set file as system file if special file such
1251            as fifo and server expecting SFU style and
1252            no Unix extensions */
1253
1254         if (create_options & CREATE_OPTION_SPECIAL)
1255                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1256         else /* BB FIXME BB */
1257                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1258
1259         if (create_options & CREATE_OPTION_READONLY)
1260                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1261
1262         /* BB FIXME BB */
1263 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1264                                                  CREATE_OPTIONS_MASK); */
1265         /* BB FIXME END BB */
1266
1267         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1268         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1269         count += name_len;
1270         inc_rfc1001_len(pSMB, count);
1271
1272         pSMB->ByteCount = cpu_to_le16(count);
1273         /* long_op set to 1 to allow for oplock break timeouts */
1274         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1275                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1276         cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1277         if (rc) {
1278                 cFYI(1, "Error in Open = %d", rc);
1279         } else {
1280         /* BB verify if wct == 15 */
1281
1282 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1283
1284                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1285                 /* Let caller know file was created so we can set the mode. */
1286                 /* Do we care about the CreateAction in any other cases? */
1287         /* BB FIXME BB */
1288 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1289                         *pOplock |= CIFS_CREATE_ACTION; */
1290         /* BB FIXME END */
1291
1292                 if (pfile_info) {
1293                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1294                         pfile_info->LastAccessTime = 0; /* BB fixme */
1295                         pfile_info->LastWriteTime = 0; /* BB fixme */
1296                         pfile_info->ChangeTime = 0;  /* BB fixme */
1297                         pfile_info->Attributes =
1298                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1299                         /* the file_info buf is endian converted by caller */
1300                         pfile_info->AllocationSize =
1301                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1302                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1303                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1304                         pfile_info->DeletePending = 0;
1305                 }
1306         }
1307
1308         cifs_buf_release(pSMB);
1309         if (rc == -EAGAIN)
1310                 goto OldOpenRetry;
1311         return rc;
1312 }
1313
1314 int
1315 CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
1316             const char *fileName, const int openDisposition,
1317             const int access_flags, const int create_options, __u16 *netfid,
1318             int *pOplock, FILE_ALL_INFO *pfile_info,
1319             const struct nls_table *nls_codepage, int remap)
1320 {
1321         int rc = -EACCES;
1322         OPEN_REQ *pSMB = NULL;
1323         OPEN_RSP *pSMBr = NULL;
1324         int bytes_returned;
1325         int name_len;
1326         __u16 count;
1327
1328 openRetry:
1329         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1330                       (void **) &pSMBr);
1331         if (rc)
1332                 return rc;
1333
1334         pSMB->AndXCommand = 0xFF;       /* none */
1335
1336         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1337                 count = 1;      /* account for one byte pad to word boundary */
1338                 name_len =
1339                     cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1340                                        fileName, PATH_MAX, nls_codepage, remap);
1341                 name_len++;     /* trailing null */
1342                 name_len *= 2;
1343                 pSMB->NameLength = cpu_to_le16(name_len);
1344         } else {                /* BB improve check for buffer overruns BB */
1345                 count = 0;      /* no pad */
1346                 name_len = strnlen(fileName, PATH_MAX);
1347                 name_len++;     /* trailing null */
1348                 pSMB->NameLength = cpu_to_le16(name_len);
1349                 strncpy(pSMB->fileName, fileName, name_len);
1350         }
1351         if (*pOplock & REQ_OPLOCK)
1352                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1353         else if (*pOplock & REQ_BATCHOPLOCK)
1354                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1355         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1356         pSMB->AllocationSize = 0;
1357         /* set file as system file if special file such
1358            as fifo and server expecting SFU style and
1359            no Unix extensions */
1360         if (create_options & CREATE_OPTION_SPECIAL)
1361                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1362         else
1363                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1364
1365         /* XP does not handle ATTR_POSIX_SEMANTICS */
1366         /* but it helps speed up case sensitive checks for other
1367         servers such as Samba */
1368         if (tcon->ses->capabilities & CAP_UNIX)
1369                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1370
1371         if (create_options & CREATE_OPTION_READONLY)
1372                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1373
1374         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1375         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1376         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1377         /* BB Expirement with various impersonation levels and verify */
1378         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1379         pSMB->SecurityFlags =
1380             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1381
1382         count += name_len;
1383         inc_rfc1001_len(pSMB, count);
1384
1385         pSMB->ByteCount = cpu_to_le16(count);
1386         /* long_op set to 1 to allow for oplock break timeouts */
1387         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1388                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1389         cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1390         if (rc) {
1391                 cFYI(1, "Error in Open = %d", rc);
1392         } else {
1393                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1394                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1395                 /* Let caller know file was created so we can set the mode. */
1396                 /* Do we care about the CreateAction in any other cases? */
1397                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1398                         *pOplock |= CIFS_CREATE_ACTION;
1399                 if (pfile_info) {
1400                         memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1401                                 36 /* CreationTime to Attributes */);
1402                         /* the file_info buf is endian converted by caller */
1403                         pfile_info->AllocationSize = pSMBr->AllocationSize;
1404                         pfile_info->EndOfFile = pSMBr->EndOfFile;
1405                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1406                         pfile_info->DeletePending = 0;
1407                 }
1408         }
1409
1410         cifs_buf_release(pSMB);
1411         if (rc == -EAGAIN)
1412                 goto openRetry;
1413         return rc;
1414 }
1415
1416 /*
1417  * Discard any remaining data in the current SMB. To do this, we borrow the
1418  * current bigbuf.
1419  */
1420 static int
1421 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1422 {
1423         unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1424         int remaining = rfclen + 4 - server->total_read;
1425         struct cifs_readdata *rdata = mid->callback_data;
1426
1427         while (remaining > 0) {
1428                 int length;
1429
1430                 length = cifs_read_from_socket(server, server->bigbuf,
1431                                 min_t(unsigned int, remaining,
1432                                     CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1433                 if (length < 0)
1434                         return length;
1435                 server->total_read += length;
1436                 remaining -= length;
1437         }
1438
1439         dequeue_mid(mid, rdata->result);
1440         return 0;
1441 }
1442
1443 static int
1444 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1445 {
1446         int length, len;
1447         unsigned int data_offset, data_len;
1448         struct cifs_readdata *rdata = mid->callback_data;
1449         char *buf = server->smallbuf;
1450         unsigned int buflen = get_rfc1002_length(buf) + 4;
1451
1452         cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1453                 mid->mid, rdata->offset, rdata->bytes);
1454
1455         /*
1456          * read the rest of READ_RSP header (sans Data array), or whatever we
1457          * can if there's not enough data. At this point, we've read down to
1458          * the Mid.
1459          */
1460         len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1461                                                         HEADER_SIZE(server) + 1;
1462
1463         rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1464         rdata->iov[0].iov_len = len;
1465
1466         length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1467         if (length < 0)
1468                 return length;
1469         server->total_read += length;
1470
1471         /* Was the SMB read successful? */
1472         rdata->result = server->ops->map_error(buf, false);
1473         if (rdata->result != 0) {
1474                 cFYI(1, "%s: server returned error %d", __func__,
1475                         rdata->result);
1476                 return cifs_readv_discard(server, mid);
1477         }
1478
1479         /* Is there enough to get to the rest of the READ_RSP header? */
1480         if (server->total_read < server->vals->read_rsp_size) {
1481                 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1482                         __func__, server->total_read,
1483                         server->vals->read_rsp_size);
1484                 rdata->result = -EIO;
1485                 return cifs_readv_discard(server, mid);
1486         }
1487
1488         data_offset = server->ops->read_data_offset(buf) + 4;
1489         if (data_offset < server->total_read) {
1490                 /*
1491                  * win2k8 sometimes sends an offset of 0 when the read
1492                  * is beyond the EOF. Treat it as if the data starts just after
1493                  * the header.
1494                  */
1495                 cFYI(1, "%s: data offset (%u) inside read response header",
1496                         __func__, data_offset);
1497                 data_offset = server->total_read;
1498         } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1499                 /* data_offset is beyond the end of smallbuf */
1500                 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1501                         __func__, data_offset);
1502                 rdata->result = -EIO;
1503                 return cifs_readv_discard(server, mid);
1504         }
1505
1506         cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1507                 server->total_read, data_offset);
1508
1509         len = data_offset - server->total_read;
1510         if (len > 0) {
1511                 /* read any junk before data into the rest of smallbuf */
1512                 rdata->iov[0].iov_base = buf + server->total_read;
1513                 rdata->iov[0].iov_len = len;
1514                 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1515                 if (length < 0)
1516                         return length;
1517                 server->total_read += length;
1518         }
1519
1520         /* set up first iov for signature check */
1521         rdata->iov[0].iov_base = buf;
1522         rdata->iov[0].iov_len = server->total_read;
1523         cFYI(1, "0: iov_base=%p iov_len=%zu",
1524                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1525
1526         /* how much data is in the response? */
1527         data_len = server->ops->read_data_length(buf);
1528         if (data_offset + data_len > buflen) {
1529                 /* data_len is corrupt -- discard frame */
1530                 rdata->result = -EIO;
1531                 return cifs_readv_discard(server, mid);
1532         }
1533
1534         /* marshal up the page array */
1535         cifs_kmap_lock();
1536         len = rdata->marshal_iov(rdata, data_len);
1537         cifs_kmap_unlock();
1538         data_len -= len;
1539
1540         /* issue the read if we have any iovecs left to fill */
1541         if (rdata->nr_iov > 1) {
1542                 length = cifs_readv_from_socket(server, &rdata->iov[1],
1543                                                 rdata->nr_iov - 1, len);
1544                 if (length < 0)
1545                         return length;
1546                 server->total_read += length;
1547         } else {
1548                 length = 0;
1549         }
1550
1551         rdata->bytes = length;
1552
1553         cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1554                 buflen, data_len);
1555
1556         /* discard anything left over */
1557         if (server->total_read < buflen)
1558                 return cifs_readv_discard(server, mid);
1559
1560         dequeue_mid(mid, false);
1561         return length;
1562 }
1563
1564 static void
1565 cifs_readv_callback(struct mid_q_entry *mid)
1566 {
1567         struct cifs_readdata *rdata = mid->callback_data;
1568         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1569         struct TCP_Server_Info *server = tcon->ses->server;
1570
1571         cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1572                 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1573
1574         switch (mid->mid_state) {
1575         case MID_RESPONSE_RECEIVED:
1576                 /* result already set, check signature */
1577                 if (server->sec_mode &
1578                     (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1579                         int rc = 0;
1580
1581                         rc = cifs_verify_signature(rdata->iov, rdata->nr_iov,
1582                                                    server,
1583                                                    mid->sequence_number + 1);
1584                         if (rc)
1585                                 cERROR(1, "SMB signature verification returned "
1586                                        "error = %d", rc);
1587                 }
1588                 /* FIXME: should this be counted toward the initiating task? */
1589                 task_io_account_read(rdata->bytes);
1590                 cifs_stats_bytes_read(tcon, rdata->bytes);
1591                 break;
1592         case MID_REQUEST_SUBMITTED:
1593         case MID_RETRY_NEEDED:
1594                 rdata->result = -EAGAIN;
1595                 break;
1596         default:
1597                 rdata->result = -EIO;
1598         }
1599
1600         queue_work(cifsiod_wq, &rdata->work);
1601         DeleteMidQEntry(mid);
1602         add_credits(server, 1, 0);
1603 }
1604
1605 /* cifs_async_readv - send an async write, and set up mid to handle result */
1606 int
1607 cifs_async_readv(struct cifs_readdata *rdata)
1608 {
1609         int rc;
1610         READ_REQ *smb = NULL;
1611         int wct;
1612         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1613
1614         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1615                 rdata->offset, rdata->bytes);
1616
1617         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1618                 wct = 12;
1619         else {
1620                 wct = 10; /* old style read */
1621                 if ((rdata->offset >> 32) > 0)  {
1622                         /* can not handle this big offset for old */
1623                         return -EIO;
1624                 }
1625         }
1626
1627         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1628         if (rc)
1629                 return rc;
1630
1631         smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1632         smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1633
1634         smb->AndXCommand = 0xFF;        /* none */
1635         smb->Fid = rdata->cfile->netfid;
1636         smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1637         if (wct == 12)
1638                 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1639         smb->Remaining = 0;
1640         smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1641         smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1642         if (wct == 12)
1643                 smb->ByteCount = 0;
1644         else {
1645                 /* old style read */
1646                 struct smb_com_readx_req *smbr =
1647                         (struct smb_com_readx_req *)smb;
1648                 smbr->ByteCount = 0;
1649         }
1650
1651         /* 4 for RFC1001 length + 1 for BCC */
1652         rdata->iov[0].iov_base = smb;
1653         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1654
1655         kref_get(&rdata->refcount);
1656         rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1657                              cifs_readv_receive, cifs_readv_callback,
1658                              rdata, 0);
1659
1660         if (rc == 0)
1661                 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1662         else
1663                 kref_put(&rdata->refcount, cifs_readdata_release);
1664
1665         cifs_small_buf_release(smb);
1666         return rc;
1667 }
1668
1669 int
1670 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1671             unsigned int *nbytes, char **buf, int *pbuf_type)
1672 {
1673         int rc = -EACCES;
1674         READ_REQ *pSMB = NULL;
1675         READ_RSP *pSMBr = NULL;
1676         char *pReadData = NULL;
1677         int wct;
1678         int resp_buf_type = 0;
1679         struct kvec iov[1];
1680         __u32 pid = io_parms->pid;
1681         __u16 netfid = io_parms->netfid;
1682         __u64 offset = io_parms->offset;
1683         struct cifs_tcon *tcon = io_parms->tcon;
1684         unsigned int count = io_parms->length;
1685
1686         cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1687         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1688                 wct = 12;
1689         else {
1690                 wct = 10; /* old style read */
1691                 if ((offset >> 32) > 0)  {
1692                         /* can not handle this big offset for old */
1693                         return -EIO;
1694                 }
1695         }
1696
1697         *nbytes = 0;
1698         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1699         if (rc)
1700                 return rc;
1701
1702         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1703         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1704
1705         /* tcon and ses pointer are checked in smb_init */
1706         if (tcon->ses->server == NULL)
1707                 return -ECONNABORTED;
1708
1709         pSMB->AndXCommand = 0xFF;       /* none */
1710         pSMB->Fid = netfid;
1711         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1712         if (wct == 12)
1713                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1714
1715         pSMB->Remaining = 0;
1716         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1717         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1718         if (wct == 12)
1719                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1720         else {
1721                 /* old style read */
1722                 struct smb_com_readx_req *pSMBW =
1723                         (struct smb_com_readx_req *)pSMB;
1724                 pSMBW->ByteCount = 0;
1725         }
1726
1727         iov[0].iov_base = (char *)pSMB;
1728         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1729         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1730                          &resp_buf_type, CIFS_LOG_ERROR);
1731         cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1732         pSMBr = (READ_RSP *)iov[0].iov_base;
1733         if (rc) {
1734                 cERROR(1, "Send error in read = %d", rc);
1735         } else {
1736                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1737                 data_length = data_length << 16;
1738                 data_length += le16_to_cpu(pSMBr->DataLength);
1739                 *nbytes = data_length;
1740
1741                 /*check that DataLength would not go beyond end of SMB */
1742                 if ((data_length > CIFSMaxBufSize)
1743                                 || (data_length > count)) {
1744                         cFYI(1, "bad length %d for count %d",
1745                                  data_length, count);
1746                         rc = -EIO;
1747                         *nbytes = 0;
1748                 } else {
1749                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1750                                         le16_to_cpu(pSMBr->DataOffset);
1751 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1752                                 cERROR(1, "Faulting on read rc = %d",rc);
1753                                 rc = -EFAULT;
1754                         }*/ /* can not use copy_to_user when using page cache*/
1755                         if (*buf)
1756                                 memcpy(*buf, pReadData, data_length);
1757                 }
1758         }
1759
1760 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1761         if (*buf) {
1762                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1763                         cifs_small_buf_release(iov[0].iov_base);
1764                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1765                         cifs_buf_release(iov[0].iov_base);
1766         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1767                 /* return buffer to caller to free */
1768                 *buf = iov[0].iov_base;
1769                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1770                         *pbuf_type = CIFS_SMALL_BUFFER;
1771                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1772                         *pbuf_type = CIFS_LARGE_BUFFER;
1773         } /* else no valid buffer on return - leave as null */
1774
1775         /* Note: On -EAGAIN error only caller can retry on handle based calls
1776                 since file handle passed in no longer valid */
1777         return rc;
1778 }
1779
1780
1781 int
1782 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1783              unsigned int *nbytes, const char *buf,
1784              const char __user *ubuf, const int long_op)
1785 {
1786         int rc = -EACCES;
1787         WRITE_REQ *pSMB = NULL;
1788         WRITE_RSP *pSMBr = NULL;
1789         int bytes_returned, wct;
1790         __u32 bytes_sent;
1791         __u16 byte_count;
1792         __u32 pid = io_parms->pid;
1793         __u16 netfid = io_parms->netfid;
1794         __u64 offset = io_parms->offset;
1795         struct cifs_tcon *tcon = io_parms->tcon;
1796         unsigned int count = io_parms->length;
1797
1798         *nbytes = 0;
1799
1800         /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1801         if (tcon->ses == NULL)
1802                 return -ECONNABORTED;
1803
1804         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1805                 wct = 14;
1806         else {
1807                 wct = 12;
1808                 if ((offset >> 32) > 0) {
1809                         /* can not handle big offset for old srv */
1810                         return -EIO;
1811                 }
1812         }
1813
1814         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1815                       (void **) &pSMBr);
1816         if (rc)
1817                 return rc;
1818
1819         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1820         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1821
1822         /* tcon and ses pointer are checked in smb_init */
1823         if (tcon->ses->server == NULL)
1824                 return -ECONNABORTED;
1825
1826         pSMB->AndXCommand = 0xFF;       /* none */
1827         pSMB->Fid = netfid;
1828         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1829         if (wct == 14)
1830                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1831
1832         pSMB->Reserved = 0xFFFFFFFF;
1833         pSMB->WriteMode = 0;
1834         pSMB->Remaining = 0;
1835
1836         /* Can increase buffer size if buffer is big enough in some cases ie we
1837         can send more if LARGE_WRITE_X capability returned by the server and if
1838         our buffer is big enough or if we convert to iovecs on socket writes
1839         and eliminate the copy to the CIFS buffer */
1840         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1841                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1842         } else {
1843                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1844                          & ~0xFF;
1845         }
1846
1847         if (bytes_sent > count)
1848                 bytes_sent = count;
1849         pSMB->DataOffset =
1850                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1851         if (buf)
1852                 memcpy(pSMB->Data, buf, bytes_sent);
1853         else if (ubuf) {
1854                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1855                         cifs_buf_release(pSMB);
1856                         return -EFAULT;
1857                 }
1858         } else if (count != 0) {
1859                 /* No buffer */
1860                 cifs_buf_release(pSMB);
1861                 return -EINVAL;
1862         } /* else setting file size with write of zero bytes */
1863         if (wct == 14)
1864                 byte_count = bytes_sent + 1; /* pad */
1865         else /* wct == 12 */
1866                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1867
1868         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1869         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1870         inc_rfc1001_len(pSMB, byte_count);
1871
1872         if (wct == 14)
1873                 pSMB->ByteCount = cpu_to_le16(byte_count);
1874         else { /* old style write has byte count 4 bytes earlier
1875                   so 4 bytes pad  */
1876                 struct smb_com_writex_req *pSMBW =
1877                         (struct smb_com_writex_req *)pSMB;
1878                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1879         }
1880
1881         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1882                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1883         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1884         if (rc) {
1885                 cFYI(1, "Send error in write = %d", rc);
1886         } else {
1887                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1888                 *nbytes = (*nbytes) << 16;
1889                 *nbytes += le16_to_cpu(pSMBr->Count);
1890
1891                 /*
1892                  * Mask off high 16 bits when bytes written as returned by the
1893                  * server is greater than bytes requested by the client. Some
1894                  * OS/2 servers are known to set incorrect CountHigh values.
1895                  */
1896                 if (*nbytes > count)
1897                         *nbytes &= 0xFFFF;
1898         }
1899
1900         cifs_buf_release(pSMB);
1901
1902         /* Note: On -EAGAIN error only caller can retry on handle based calls
1903                 since file handle passed in no longer valid */
1904
1905         return rc;
1906 }
1907
1908 void
1909 cifs_writedata_release(struct kref *refcount)
1910 {
1911         struct cifs_writedata *wdata = container_of(refcount,
1912                                         struct cifs_writedata, refcount);
1913
1914         if (wdata->cfile)
1915                 cifsFileInfo_put(wdata->cfile);
1916
1917         kfree(wdata);
1918 }
1919
1920 /*
1921  * Write failed with a retryable error. Resend the write request. It's also
1922  * possible that the page was redirtied so re-clean the page.
1923  */
1924 static void
1925 cifs_writev_requeue(struct cifs_writedata *wdata)
1926 {
1927         int i, rc;
1928         struct inode *inode = wdata->cfile->dentry->d_inode;
1929
1930         for (i = 0; i < wdata->nr_pages; i++) {
1931                 lock_page(wdata->pages[i]);
1932                 clear_page_dirty_for_io(wdata->pages[i]);
1933         }
1934
1935         do {
1936                 rc = cifs_async_writev(wdata);
1937         } while (rc == -EAGAIN);
1938
1939         for (i = 0; i < wdata->nr_pages; i++) {
1940                 if (rc != 0)
1941                         SetPageError(wdata->pages[i]);
1942                 unlock_page(wdata->pages[i]);
1943         }
1944
1945         mapping_set_error(inode->i_mapping, rc);
1946         kref_put(&wdata->refcount, cifs_writedata_release);
1947 }
1948
1949 void
1950 cifs_writev_complete(struct work_struct *work)
1951 {
1952         struct cifs_writedata *wdata = container_of(work,
1953                                                 struct cifs_writedata, work);
1954         struct inode *inode = wdata->cfile->dentry->d_inode;
1955         int i = 0;
1956
1957         if (wdata->result == 0) {
1958                 spin_lock(&inode->i_lock);
1959                 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1960                 spin_unlock(&inode->i_lock);
1961                 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1962                                          wdata->bytes);
1963         } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1964                 return cifs_writev_requeue(wdata);
1965
1966         for (i = 0; i < wdata->nr_pages; i++) {
1967                 struct page *page = wdata->pages[i];
1968                 if (wdata->result == -EAGAIN)
1969                         __set_page_dirty_nobuffers(page);
1970                 else if (wdata->result < 0)
1971                         SetPageError(page);
1972                 end_page_writeback(page);
1973                 page_cache_release(page);
1974         }
1975         if (wdata->result != -EAGAIN)
1976                 mapping_set_error(inode->i_mapping, wdata->result);
1977         kref_put(&wdata->refcount, cifs_writedata_release);
1978 }
1979
1980 struct cifs_writedata *
1981 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1982 {
1983         struct cifs_writedata *wdata;
1984
1985         /* this would overflow */
1986         if (nr_pages == 0) {
1987                 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1988                 return NULL;
1989         }
1990
1991         /* writedata + number of page pointers */
1992         wdata = kzalloc(sizeof(*wdata) +
1993                         sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1994         if (wdata != NULL) {
1995                 kref_init(&wdata->refcount);
1996                 INIT_LIST_HEAD(&wdata->list);
1997                 init_completion(&wdata->done);
1998                 INIT_WORK(&wdata->work, complete);
1999         }
2000         return wdata;
2001 }
2002
2003 /*
2004  * Check the mid_state and signature on received buffer (if any), and queue the
2005  * workqueue completion task.
2006  */
2007 static void
2008 cifs_writev_callback(struct mid_q_entry *mid)
2009 {
2010         struct cifs_writedata *wdata = mid->callback_data;
2011         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2012         unsigned int written;
2013         WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2014
2015         switch (mid->mid_state) {
2016         case MID_RESPONSE_RECEIVED:
2017                 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2018                 if (wdata->result != 0)
2019                         break;
2020
2021                 written = le16_to_cpu(smb->CountHigh);
2022                 written <<= 16;
2023                 written += le16_to_cpu(smb->Count);
2024                 /*
2025                  * Mask off high 16 bits when bytes written as returned
2026                  * by the server is greater than bytes requested by the
2027                  * client. OS/2 servers are known to set incorrect
2028                  * CountHigh values.
2029                  */
2030                 if (written > wdata->bytes)
2031                         written &= 0xFFFF;
2032
2033                 if (written < wdata->bytes)
2034                         wdata->result = -ENOSPC;
2035                 else
2036                         wdata->bytes = written;
2037                 break;
2038         case MID_REQUEST_SUBMITTED:
2039         case MID_RETRY_NEEDED:
2040                 wdata->result = -EAGAIN;
2041                 break;
2042         default:
2043                 wdata->result = -EIO;
2044                 break;
2045         }
2046
2047         queue_work(cifsiod_wq, &wdata->work);
2048         DeleteMidQEntry(mid);
2049         add_credits(tcon->ses->server, 1, 0);
2050 }
2051
2052 /* cifs_async_writev - send an async write, and set up mid to handle result */
2053 int
2054 cifs_async_writev(struct cifs_writedata *wdata)
2055 {
2056         int i, rc = -EACCES;
2057         WRITE_REQ *smb = NULL;
2058         int wct;
2059         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2060         struct kvec *iov = NULL;
2061
2062         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2063                 wct = 14;
2064         } else {
2065                 wct = 12;
2066                 if (wdata->offset >> 32 > 0) {
2067                         /* can not handle big offset for old srv */
2068                         return -EIO;
2069                 }
2070         }
2071
2072         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2073         if (rc)
2074                 goto async_writev_out;
2075
2076         /* 1 iov per page + 1 for header */
2077         iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2078         if (iov == NULL) {
2079                 rc = -ENOMEM;
2080                 goto async_writev_out;
2081         }
2082
2083         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2084         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2085
2086         smb->AndXCommand = 0xFF;        /* none */
2087         smb->Fid = wdata->cfile->netfid;
2088         smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2089         if (wct == 14)
2090                 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2091         smb->Reserved = 0xFFFFFFFF;
2092         smb->WriteMode = 0;
2093         smb->Remaining = 0;
2094
2095         smb->DataOffset =
2096             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2097
2098         /* 4 for RFC1001 length + 1 for BCC */
2099         iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2100         iov[0].iov_base = smb;
2101
2102         /*
2103          * This function should marshal up the page array into the kvec
2104          * array, reserving [0] for the header. It should kmap the pages
2105          * and set the iov_len properly for each one. It may also set
2106          * wdata->bytes too.
2107          */
2108         cifs_kmap_lock();
2109         wdata->marshal_iov(iov, wdata);
2110         cifs_kmap_unlock();
2111
2112         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2113
2114         smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2115         smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2116
2117         if (wct == 14) {
2118                 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2119                 put_bcc(wdata->bytes + 1, &smb->hdr);
2120         } else {
2121                 /* wct == 12 */
2122                 struct smb_com_writex_req *smbw =
2123                                 (struct smb_com_writex_req *)smb;
2124                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2125                 put_bcc(wdata->bytes + 5, &smbw->hdr);
2126                 iov[0].iov_len += 4; /* pad bigger by four bytes */
2127         }
2128
2129         kref_get(&wdata->refcount);
2130         rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2131                              NULL, cifs_writev_callback, wdata, 0);
2132
2133         if (rc == 0)
2134                 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2135         else
2136                 kref_put(&wdata->refcount, cifs_writedata_release);
2137
2138         /* send is done, unmap pages */
2139         for (i = 0; i < wdata->nr_pages; i++)
2140                 kunmap(wdata->pages[i]);
2141
2142 async_writev_out:
2143         cifs_small_buf_release(smb);
2144         kfree(iov);
2145         return rc;
2146 }
2147
2148 int
2149 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2150               unsigned int *nbytes, struct kvec *iov, int n_vec,
2151               const int long_op)
2152 {
2153         int rc = -EACCES;
2154         WRITE_REQ *pSMB = NULL;
2155         int wct;
2156         int smb_hdr_len;
2157         int resp_buf_type = 0;
2158         __u32 pid = io_parms->pid;
2159         __u16 netfid = io_parms->netfid;
2160         __u64 offset = io_parms->offset;
2161         struct cifs_tcon *tcon = io_parms->tcon;
2162         unsigned int count = io_parms->length;
2163
2164         *nbytes = 0;
2165
2166         cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2167
2168         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2169                 wct = 14;
2170         } else {
2171                 wct = 12;
2172                 if ((offset >> 32) > 0) {
2173                         /* can not handle big offset for old srv */
2174                         return -EIO;
2175                 }
2176         }
2177         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2178         if (rc)
2179                 return rc;
2180
2181         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2182         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2183
2184         /* tcon and ses pointer are checked in smb_init */
2185         if (tcon->ses->server == NULL)
2186                 return -ECONNABORTED;
2187
2188         pSMB->AndXCommand = 0xFF;       /* none */
2189         pSMB->Fid = netfid;
2190         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2191         if (wct == 14)
2192                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2193         pSMB->Reserved = 0xFFFFFFFF;
2194         pSMB->WriteMode = 0;
2195         pSMB->Remaining = 0;
2196
2197         pSMB->DataOffset =
2198             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2199
2200         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2201         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2202         /* header + 1 byte pad */
2203         smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2204         if (wct == 14)
2205                 inc_rfc1001_len(pSMB, count + 1);
2206         else /* wct == 12 */
2207                 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2208         if (wct == 14)
2209                 pSMB->ByteCount = cpu_to_le16(count + 1);
2210         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2211                 struct smb_com_writex_req *pSMBW =
2212                                 (struct smb_com_writex_req *)pSMB;
2213                 pSMBW->ByteCount = cpu_to_le16(count + 5);
2214         }
2215         iov[0].iov_base = pSMB;
2216         if (wct == 14)
2217                 iov[0].iov_len = smb_hdr_len + 4;
2218         else /* wct == 12 pad bigger by four bytes */
2219                 iov[0].iov_len = smb_hdr_len + 8;
2220
2221
2222         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2223                           long_op);
2224         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2225         if (rc) {
2226                 cFYI(1, "Send error Write2 = %d", rc);
2227         } else if (resp_buf_type == 0) {
2228                 /* presumably this can not happen, but best to be safe */
2229                 rc = -EIO;
2230         } else {
2231                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2232                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2233                 *nbytes = (*nbytes) << 16;
2234                 *nbytes += le16_to_cpu(pSMBr->Count);
2235
2236                 /*
2237                  * Mask off high 16 bits when bytes written as returned by the
2238                  * server is greater than bytes requested by the client. OS/2
2239                  * servers are known to set incorrect CountHigh values.
2240                  */
2241                 if (*nbytes > count)
2242                         *nbytes &= 0xFFFF;
2243         }
2244
2245 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2246         if (resp_buf_type == CIFS_SMALL_BUFFER)
2247                 cifs_small_buf_release(iov[0].iov_base);
2248         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2249                 cifs_buf_release(iov[0].iov_base);
2250
2251         /* Note: On -EAGAIN error only caller can retry on handle based calls
2252                 since file handle passed in no longer valid */
2253
2254         return rc;
2255 }
2256
2257 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2258                const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2259                const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2260 {
2261         int rc = 0;
2262         LOCK_REQ *pSMB = NULL;
2263         struct kvec iov[2];
2264         int resp_buf_type;
2265         __u16 count;
2266
2267         cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2268
2269         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2270         if (rc)
2271                 return rc;
2272
2273         pSMB->Timeout = 0;
2274         pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2275         pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2276         pSMB->LockType = lock_type;
2277         pSMB->AndXCommand = 0xFF; /* none */
2278         pSMB->Fid = netfid; /* netfid stays le */
2279
2280         count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2281         inc_rfc1001_len(pSMB, count);
2282         pSMB->ByteCount = cpu_to_le16(count);
2283
2284         iov[0].iov_base = (char *)pSMB;
2285         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2286                          (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2287         iov[1].iov_base = (char *)buf;
2288         iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2289
2290         cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2291         rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2292         if (rc)
2293                 cFYI(1, "Send error in cifs_lockv = %d", rc);
2294
2295         return rc;
2296 }
2297
2298 int
2299 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2300             const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2301             const __u64 offset, const __u32 numUnlock,
2302             const __u32 numLock, const __u8 lockType,
2303             const bool waitFlag, const __u8 oplock_level)
2304 {
2305         int rc = 0;
2306         LOCK_REQ *pSMB = NULL;
2307 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2308         int bytes_returned;
2309         int flags = 0;
2310         __u16 count;
2311
2312         cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2313         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2314
2315         if (rc)
2316                 return rc;
2317
2318         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2319                 /* no response expected */
2320                 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2321                 pSMB->Timeout = 0;
2322         } else if (waitFlag) {
2323                 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2324                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2325         } else {
2326                 pSMB->Timeout = 0;
2327         }
2328
2329         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2330         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2331         pSMB->LockType = lockType;
2332         pSMB->OplockLevel = oplock_level;
2333         pSMB->AndXCommand = 0xFF;       /* none */
2334         pSMB->Fid = smb_file_id; /* netfid stays le */
2335
2336         if ((numLock != 0) || (numUnlock != 0)) {
2337                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2338                 /* BB where to store pid high? */
2339                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2340                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2341                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2342                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2343                 count = sizeof(LOCKING_ANDX_RANGE);
2344         } else {
2345                 /* oplock break */
2346                 count = 0;
2347         }
2348         inc_rfc1001_len(pSMB, count);
2349         pSMB->ByteCount = cpu_to_le16(count);
2350
2351         if (waitFlag) {
2352                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2353                         (struct smb_hdr *) pSMB, &bytes_returned);
2354                 cifs_small_buf_release(pSMB);
2355         } else {
2356                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2357                 /* SMB buffer freed by function above */
2358         }
2359         cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2360         if (rc)
2361                 cFYI(1, "Send error in Lock = %d", rc);
2362
2363         /* Note: On -EAGAIN error only caller can retry on handle based calls
2364         since file handle passed in no longer valid */
2365         return rc;
2366 }
2367
2368 int
2369 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2370                 const __u16 smb_file_id, const __u32 netpid,
2371                 const loff_t start_offset, const __u64 len,
2372                 struct file_lock *pLockData, const __u16 lock_type,
2373                 const bool waitFlag)
2374 {
2375         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2376         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2377         struct cifs_posix_lock *parm_data;
2378         int rc = 0;
2379         int timeout = 0;
2380         int bytes_returned = 0;
2381         int resp_buf_type = 0;
2382         __u16 params, param_offset, offset, byte_count, count;
2383         struct kvec iov[1];
2384
2385         cFYI(1, "Posix Lock");
2386
2387         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2388
2389         if (rc)
2390                 return rc;
2391
2392         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2393
2394         params = 6;
2395         pSMB->MaxSetupCount = 0;
2396         pSMB->Reserved = 0;
2397         pSMB->Flags = 0;
2398         pSMB->Reserved2 = 0;
2399         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2400         offset = param_offset + params;
2401
2402         count = sizeof(struct cifs_posix_lock);
2403         pSMB->MaxParameterCount = cpu_to_le16(2);
2404         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2405         pSMB->SetupCount = 1;
2406         pSMB->Reserved3 = 0;
2407         if (pLockData)
2408                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2409         else
2410                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2411         byte_count = 3 /* pad */  + params + count;
2412         pSMB->DataCount = cpu_to_le16(count);
2413         pSMB->ParameterCount = cpu_to_le16(params);
2414         pSMB->TotalDataCount = pSMB->DataCount;
2415         pSMB->TotalParameterCount = pSMB->ParameterCount;
2416         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2417         parm_data = (struct cifs_posix_lock *)
2418                         (((char *) &pSMB->hdr.Protocol) + offset);
2419
2420         parm_data->lock_type = cpu_to_le16(lock_type);
2421         if (waitFlag) {
2422                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2423                 parm_data->lock_flags = cpu_to_le16(1);
2424                 pSMB->Timeout = cpu_to_le32(-1);
2425         } else
2426                 pSMB->Timeout = 0;
2427
2428         parm_data->pid = cpu_to_le32(netpid);
2429         parm_data->start = cpu_to_le64(start_offset);
2430         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2431
2432         pSMB->DataOffset = cpu_to_le16(offset);
2433         pSMB->Fid = smb_file_id;
2434         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2435         pSMB->Reserved4 = 0;
2436         inc_rfc1001_len(pSMB, byte_count);
2437         pSMB->ByteCount = cpu_to_le16(byte_count);
2438         if (waitFlag) {
2439                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2440                         (struct smb_hdr *) pSMBr, &bytes_returned);
2441         } else {
2442                 iov[0].iov_base = (char *)pSMB;
2443                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2444                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2445                                 &resp_buf_type, timeout);
2446                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2447                                 not try to free it twice below on exit */
2448                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2449         }
2450
2451         if (rc) {
2452                 cFYI(1, "Send error in Posix Lock = %d", rc);
2453         } else if (pLockData) {
2454                 /* lock structure can be returned on get */
2455                 __u16 data_offset;
2456                 __u16 data_count;
2457                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2458
2459                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2460                         rc = -EIO;      /* bad smb */
2461                         goto plk_err_exit;
2462                 }
2463                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2464                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2465                 if (data_count < sizeof(struct cifs_posix_lock)) {
2466                         rc = -EIO;
2467                         goto plk_err_exit;
2468                 }
2469                 parm_data = (struct cifs_posix_lock *)
2470                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2471                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2472                         pLockData->fl_type = F_UNLCK;
2473                 else {
2474                         if (parm_data->lock_type ==
2475                                         __constant_cpu_to_le16(CIFS_RDLCK))
2476                                 pLockData->fl_type = F_RDLCK;
2477                         else if (parm_data->lock_type ==
2478                                         __constant_cpu_to_le16(CIFS_WRLCK))
2479                                 pLockData->fl_type = F_WRLCK;
2480
2481                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2482                         pLockData->fl_end = pLockData->fl_start +
2483                                         le64_to_cpu(parm_data->length) - 1;
2484                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2485                 }
2486         }
2487
2488 plk_err_exit:
2489         if (pSMB)
2490                 cifs_small_buf_release(pSMB);
2491
2492         if (resp_buf_type == CIFS_SMALL_BUFFER)
2493                 cifs_small_buf_release(iov[0].iov_base);
2494         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2495                 cifs_buf_release(iov[0].iov_base);
2496
2497         /* Note: On -EAGAIN error only caller can retry on handle based calls
2498            since file handle passed in no longer valid */
2499
2500         return rc;
2501 }
2502
2503
2504 int
2505 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2506 {
2507         int rc = 0;
2508         CLOSE_REQ *pSMB = NULL;
2509         cFYI(1, "In CIFSSMBClose");
2510
2511 /* do not retry on dead session on close */
2512         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2513         if (rc == -EAGAIN)
2514                 return 0;
2515         if (rc)
2516                 return rc;
2517
2518         pSMB->FileID = (__u16) smb_file_id;
2519         pSMB->LastWriteTime = 0xFFFFFFFF;
2520         pSMB->ByteCount = 0;
2521         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2522         cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2523         if (rc) {
2524                 if (rc != -EINTR) {
2525                         /* EINTR is expected when user ctl-c to kill app */
2526                         cERROR(1, "Send error in Close = %d", rc);
2527                 }
2528         }
2529
2530         /* Since session is dead, file will be closed on server already */
2531         if (rc == -EAGAIN)
2532                 rc = 0;
2533
2534         return rc;
2535 }
2536
2537 int
2538 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2539 {
2540         int rc = 0;
2541         FLUSH_REQ *pSMB = NULL;
2542         cFYI(1, "In CIFSSMBFlush");
2543
2544         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2545         if (rc)
2546                 return rc;
2547
2548         pSMB->FileID = (__u16) smb_file_id;
2549         pSMB->ByteCount = 0;
2550         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2551         cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2552         if (rc)
2553                 cERROR(1, "Send error in Flush = %d", rc);
2554
2555         return rc;
2556 }
2557
2558 int
2559 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2560               const char *fromName, const char *toName,
2561               const struct nls_table *nls_codepage, int remap)
2562 {
2563         int rc = 0;
2564         RENAME_REQ *pSMB = NULL;
2565         RENAME_RSP *pSMBr = NULL;
2566         int bytes_returned;
2567         int name_len, name_len2;
2568         __u16 count;
2569
2570         cFYI(1, "In CIFSSMBRename");
2571 renameRetry:
2572         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2573                       (void **) &pSMBr);
2574         if (rc)
2575                 return rc;
2576
2577         pSMB->BufferFormat = 0x04;
2578         pSMB->SearchAttributes =
2579             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2580                         ATTR_DIRECTORY);
2581
2582         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2583                 name_len =
2584                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2585                                        PATH_MAX, nls_codepage, remap);
2586                 name_len++;     /* trailing null */
2587                 name_len *= 2;
2588                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2589         /* protocol requires ASCII signature byte on Unicode string */
2590                 pSMB->OldFileName[name_len + 1] = 0x00;
2591                 name_len2 =
2592                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2593                                        toName, PATH_MAX, nls_codepage, remap);
2594                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2595                 name_len2 *= 2; /* convert to bytes */
2596         } else {        /* BB improve the check for buffer overruns BB */
2597                 name_len = strnlen(fromName, PATH_MAX);
2598                 name_len++;     /* trailing null */
2599                 strncpy(pSMB->OldFileName, fromName, name_len);
2600                 name_len2 = strnlen(toName, PATH_MAX);
2601                 name_len2++;    /* trailing null */
2602                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2603                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2604                 name_len2++;    /* trailing null */
2605                 name_len2++;    /* signature byte */
2606         }
2607
2608         count = 1 /* 1st signature byte */  + name_len + name_len2;
2609         inc_rfc1001_len(pSMB, count);
2610         pSMB->ByteCount = cpu_to_le16(count);
2611
2612         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2613                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2614         cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2615         if (rc)
2616                 cFYI(1, "Send error in rename = %d", rc);
2617
2618         cifs_buf_release(pSMB);
2619
2620         if (rc == -EAGAIN)
2621                 goto renameRetry;
2622
2623         return rc;
2624 }
2625
2626 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2627                 int netfid, const char *target_name,
2628                 const struct nls_table *nls_codepage, int remap)
2629 {
2630         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2631         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2632         struct set_file_rename *rename_info;
2633         char *data_offset;
2634         char dummy_string[30];
2635         int rc = 0;
2636         int bytes_returned = 0;
2637         int len_of_str;
2638         __u16 params, param_offset, offset, count, byte_count;
2639
2640         cFYI(1, "Rename to File by handle");
2641         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2642                         (void **) &pSMBr);
2643         if (rc)
2644                 return rc;
2645
2646         params = 6;
2647         pSMB->MaxSetupCount = 0;
2648         pSMB->Reserved = 0;
2649         pSMB->Flags = 0;
2650         pSMB->Timeout = 0;
2651         pSMB->Reserved2 = 0;
2652         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2653         offset = param_offset + params;
2654
2655         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2656         rename_info = (struct set_file_rename *) data_offset;
2657         pSMB->MaxParameterCount = cpu_to_le16(2);
2658         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2659         pSMB->SetupCount = 1;
2660         pSMB->Reserved3 = 0;
2661         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2662         byte_count = 3 /* pad */  + params;
2663         pSMB->ParameterCount = cpu_to_le16(params);
2664         pSMB->TotalParameterCount = pSMB->ParameterCount;
2665         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2666         pSMB->DataOffset = cpu_to_le16(offset);
2667         /* construct random name ".cifs_tmp<inodenum><mid>" */
2668         rename_info->overwrite = cpu_to_le32(1);
2669         rename_info->root_fid  = 0;
2670         /* unicode only call */
2671         if (target_name == NULL) {
2672                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2673                 len_of_str =
2674                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2675                                         dummy_string, 24, nls_codepage, remap);
2676         } else {
2677                 len_of_str =
2678                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2679                                         target_name, PATH_MAX, nls_codepage,
2680                                         remap);
2681         }
2682         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2683         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2684         byte_count += count;
2685         pSMB->DataCount = cpu_to_le16(count);
2686         pSMB->TotalDataCount = pSMB->DataCount;
2687         pSMB->Fid = netfid;
2688         pSMB->InformationLevel =
2689                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2690         pSMB->Reserved4 = 0;
2691         inc_rfc1001_len(pSMB, byte_count);
2692         pSMB->ByteCount = cpu_to_le16(byte_count);
2693         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2694                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2695         cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2696         if (rc)
2697                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2698
2699         cifs_buf_release(pSMB);
2700
2701         /* Note: On -EAGAIN error only caller can retry on handle based calls
2702                 since file handle passed in no longer valid */
2703
2704         return rc;
2705 }
2706
2707 int
2708 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2709             const char *fromName, const __u16 target_tid, const char *toName,
2710             const int flags, const struct nls_table *nls_codepage, int remap)
2711 {
2712         int rc = 0;
2713         COPY_REQ *pSMB = NULL;
2714         COPY_RSP *pSMBr = NULL;
2715         int bytes_returned;
2716         int name_len, name_len2;
2717         __u16 count;
2718
2719         cFYI(1, "In CIFSSMBCopy");
2720 copyRetry:
2721         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2722                         (void **) &pSMBr);
2723         if (rc)
2724                 return rc;
2725
2726         pSMB->BufferFormat = 0x04;
2727         pSMB->Tid2 = target_tid;
2728
2729         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2730
2731         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2732                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2733                                               fromName, PATH_MAX, nls_codepage,
2734                                               remap);
2735                 name_len++;     /* trailing null */
2736                 name_len *= 2;
2737                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2738                 /* protocol requires ASCII signature byte on Unicode string */
2739                 pSMB->OldFileName[name_len + 1] = 0x00;
2740                 name_len2 =
2741                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2742                                        toName, PATH_MAX, nls_codepage, remap);
2743                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2744                 name_len2 *= 2; /* convert to bytes */
2745         } else {        /* BB improve the check for buffer overruns BB */
2746                 name_len = strnlen(fromName, PATH_MAX);
2747                 name_len++;     /* trailing null */
2748                 strncpy(pSMB->OldFileName, fromName, name_len);
2749                 name_len2 = strnlen(toName, PATH_MAX);
2750                 name_len2++;    /* trailing null */
2751                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2752                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2753                 name_len2++;    /* trailing null */
2754                 name_len2++;    /* signature byte */
2755         }
2756
2757         count = 1 /* 1st signature byte */  + name_len + name_len2;
2758         inc_rfc1001_len(pSMB, count);
2759         pSMB->ByteCount = cpu_to_le16(count);
2760
2761         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2762                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2763         if (rc) {
2764                 cFYI(1, "Send error in copy = %d with %d files copied",
2765                         rc, le16_to_cpu(pSMBr->CopyCount));
2766         }
2767         cifs_buf_release(pSMB);
2768
2769         if (rc == -EAGAIN)
2770                 goto copyRetry;
2771
2772         return rc;
2773 }
2774
2775 int
2776 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2777                       const char *fromName, const char *toName,
2778                       const struct nls_table *nls_codepage)
2779 {
2780         TRANSACTION2_SPI_REQ *pSMB = NULL;
2781         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2782         char *data_offset;
2783         int name_len;
2784         int name_len_target;
2785         int rc = 0;
2786         int bytes_returned = 0;
2787         __u16 params, param_offset, offset, byte_count;
2788
2789         cFYI(1, "In Symlink Unix style");
2790 createSymLinkRetry:
2791         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2792                       (void **) &pSMBr);
2793         if (rc)
2794                 return rc;
2795
2796         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2797                 name_len =
2798                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2799                                     /* find define for this maxpathcomponent */
2800                                     PATH_MAX, nls_codepage);
2801                 name_len++;     /* trailing null */
2802                 name_len *= 2;
2803
2804         } else {        /* BB improve the check for buffer overruns BB */
2805                 name_len = strnlen(fromName, PATH_MAX);
2806                 name_len++;     /* trailing null */
2807                 strncpy(pSMB->FileName, fromName, name_len);
2808         }
2809         params = 6 + name_len;
2810         pSMB->MaxSetupCount = 0;
2811         pSMB->Reserved = 0;
2812         pSMB->Flags = 0;
2813         pSMB->Timeout = 0;
2814         pSMB->Reserved2 = 0;
2815         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2816                                 InformationLevel) - 4;
2817         offset = param_offset + params;
2818
2819         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2820         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2821                 name_len_target =
2822                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2823                                     /* find define for this maxpathcomponent */
2824                                     , nls_codepage);
2825                 name_len_target++;      /* trailing null */
2826                 name_len_target *= 2;
2827         } else {        /* BB improve the check for buffer overruns BB */
2828                 name_len_target = strnlen(toName, PATH_MAX);
2829                 name_len_target++;      /* trailing null */
2830                 strncpy(data_offset, toName, name_len_target);
2831         }
2832
2833         pSMB->MaxParameterCount = cpu_to_le16(2);
2834         /* BB find exact max on data count below from sess */
2835         pSMB->MaxDataCount = cpu_to_le16(1000);
2836         pSMB->SetupCount = 1;
2837         pSMB->Reserved3 = 0;
2838         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2839         byte_count = 3 /* pad */  + params + name_len_target;
2840         pSMB->DataCount = cpu_to_le16(name_len_target);
2841         pSMB->ParameterCount = cpu_to_le16(params);
2842         pSMB->TotalDataCount = pSMB->DataCount;
2843         pSMB->TotalParameterCount = pSMB->ParameterCount;
2844         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2845         pSMB->DataOffset = cpu_to_le16(offset);
2846         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2847         pSMB->Reserved4 = 0;
2848         inc_rfc1001_len(pSMB, byte_count);
2849         pSMB->ByteCount = cpu_to_le16(byte_count);
2850         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2851                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2852         cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2853         if (rc)
2854                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2855
2856         cifs_buf_release(pSMB);
2857
2858         if (rc == -EAGAIN)
2859                 goto createSymLinkRetry;
2860
2861         return rc;
2862 }
2863
2864 int
2865 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2866                        const char *fromName, const char *toName,
2867                        const struct nls_table *nls_codepage, int remap)
2868 {
2869         TRANSACTION2_SPI_REQ *pSMB = NULL;
2870         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2871         char *data_offset;
2872         int name_len;
2873         int name_len_target;
2874         int rc = 0;
2875         int bytes_returned = 0;
2876         __u16 params, param_offset, offset, byte_count;
2877
2878         cFYI(1, "In Create Hard link Unix style");
2879 createHardLinkRetry:
2880         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2881                       (void **) &pSMBr);
2882         if (rc)
2883                 return rc;
2884
2885         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2886                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2887                                               PATH_MAX, nls_codepage, remap);
2888                 name_len++;     /* trailing null */
2889                 name_len *= 2;
2890
2891         } else {        /* BB improve the check for buffer overruns BB */
2892                 name_len = strnlen(toName, PATH_MAX);
2893                 name_len++;     /* trailing null */
2894                 strncpy(pSMB->FileName, toName, name_len);
2895         }
2896         params = 6 + name_len;
2897         pSMB->MaxSetupCount = 0;
2898         pSMB->Reserved = 0;
2899         pSMB->Flags = 0;
2900         pSMB->Timeout = 0;
2901         pSMB->Reserved2 = 0;
2902         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2903                                 InformationLevel) - 4;
2904         offset = param_offset + params;
2905
2906         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2907         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2908                 name_len_target =
2909                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2910                                        PATH_MAX, nls_codepage, remap);
2911                 name_len_target++;      /* trailing null */
2912                 name_len_target *= 2;
2913         } else {        /* BB improve the check for buffer overruns BB */
2914                 name_len_target = strnlen(fromName, PATH_MAX);
2915                 name_len_target++;      /* trailing null */
2916                 strncpy(data_offset, fromName, name_len_target);
2917         }
2918
2919         pSMB->MaxParameterCount = cpu_to_le16(2);
2920         /* BB find exact max on data count below from sess*/
2921         pSMB->MaxDataCount = cpu_to_le16(1000);
2922         pSMB->SetupCount = 1;
2923         pSMB->Reserved3 = 0;
2924         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2925         byte_count = 3 /* pad */  + params + name_len_target;
2926         pSMB->ParameterCount = cpu_to_le16(params);
2927         pSMB->TotalParameterCount = pSMB->ParameterCount;
2928         pSMB->DataCount = cpu_to_le16(name_len_target);
2929         pSMB->TotalDataCount = pSMB->DataCount;
2930         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2931         pSMB->DataOffset = cpu_to_le16(offset);
2932         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2933         pSMB->Reserved4 = 0;
2934         inc_rfc1001_len(pSMB, byte_count);
2935         pSMB->ByteCount = cpu_to_le16(byte_count);
2936         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2937                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2938         cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2939         if (rc)
2940                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2941
2942         cifs_buf_release(pSMB);
2943         if (rc == -EAGAIN)
2944                 goto createHardLinkRetry;
2945
2946         return rc;
2947 }
2948
2949 int
2950 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2951                    const char *fromName, const char *toName,
2952                    const struct nls_table *nls_codepage, int remap)
2953 {
2954         int rc = 0;
2955         NT_RENAME_REQ *pSMB = NULL;
2956         RENAME_RSP *pSMBr = NULL;
2957         int bytes_returned;
2958         int name_len, name_len2;
2959         __u16 count;
2960
2961         cFYI(1, "In CIFSCreateHardLink");
2962 winCreateHardLinkRetry:
2963
2964         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2965                       (void **) &pSMBr);
2966         if (rc)
2967                 return rc;
2968
2969         pSMB->SearchAttributes =
2970             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2971                         ATTR_DIRECTORY);
2972         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2973         pSMB->ClusterCount = 0;
2974
2975         pSMB->BufferFormat = 0x04;
2976
2977         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2978                 name_len =
2979                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2980                                        PATH_MAX, nls_codepage, remap);
2981                 name_len++;     /* trailing null */
2982                 name_len *= 2;
2983
2984                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2985                 pSMB->OldFileName[name_len] = 0x04;
2986                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2987                 name_len2 =
2988                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2989                                        toName, PATH_MAX, nls_codepage, remap);
2990                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2991                 name_len2 *= 2; /* convert to bytes */
2992         } else {        /* BB improve the check for buffer overruns BB */
2993                 name_len = strnlen(fromName, PATH_MAX);
2994                 name_len++;     /* trailing null */
2995                 strncpy(pSMB->OldFileName, fromName, name_len);
2996                 name_len2 = strnlen(toName, PATH_MAX);
2997                 name_len2++;    /* trailing null */
2998                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2999                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
3000                 name_len2++;    /* trailing null */
3001                 name_len2++;    /* signature byte */
3002         }
3003
3004         count = 1 /* string type byte */  + name_len + name_len2;
3005         inc_rfc1001_len(pSMB, count);
3006         pSMB->ByteCount = cpu_to_le16(count);
3007
3008         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3009                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3010         cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3011         if (rc)
3012                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3013
3014         cifs_buf_release(pSMB);
3015         if (rc == -EAGAIN)
3016                 goto winCreateHardLinkRetry;
3017
3018         return rc;
3019 }
3020
3021 int
3022 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3023                         const unsigned char *searchName, char **symlinkinfo,
3024                         const struct nls_table *nls_codepage)
3025 {
3026 /* SMB_QUERY_FILE_UNIX_LINK */
3027         TRANSACTION2_QPI_REQ *pSMB = NULL;
3028         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3029         int rc = 0;
3030         int bytes_returned;
3031         int name_len;
3032         __u16 params, byte_count;
3033         char *data_start;
3034
3035         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3036
3037 querySymLinkRetry:
3038         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3039                       (void **) &pSMBr);
3040         if (rc)
3041                 return rc;
3042
3043         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3044                 name_len =
3045                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3046                                         PATH_MAX, nls_codepage);
3047                 name_len++;     /* trailing null */
3048                 name_len *= 2;
3049         } else {        /* BB improve the check for buffer overruns BB */
3050                 name_len = strnlen(searchName, PATH_MAX);
3051                 name_len++;     /* trailing null */
3052                 strncpy(pSMB->FileName, searchName, name_len);
3053         }
3054
3055         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3056         pSMB->TotalDataCount = 0;
3057         pSMB->MaxParameterCount = cpu_to_le16(2);
3058         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3059         pSMB->MaxSetupCount = 0;
3060         pSMB->Reserved = 0;
3061         pSMB->Flags = 0;
3062         pSMB->Timeout = 0;
3063         pSMB->Reserved2 = 0;
3064         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3065         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3066         pSMB->DataCount = 0;
3067         pSMB->DataOffset = 0;
3068         pSMB->SetupCount = 1;
3069         pSMB->Reserved3 = 0;
3070         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3071         byte_count = params + 1 /* pad */ ;
3072         pSMB->TotalParameterCount = cpu_to_le16(params);
3073         pSMB->ParameterCount = pSMB->TotalParameterCount;
3074         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3075         pSMB->Reserved4 = 0;
3076         inc_rfc1001_len(pSMB, byte_count);
3077         pSMB->ByteCount = cpu_to_le16(byte_count);
3078
3079         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3080                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3081         if (rc) {
3082                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3083         } else {
3084                 /* decode response */
3085
3086                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3087                 /* BB also check enough total bytes returned */
3088                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3089                         rc = -EIO;
3090                 else {
3091                         bool is_unicode;
3092                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3093
3094                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3095                                            le16_to_cpu(pSMBr->t2.DataOffset);
3096
3097                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3098                                 is_unicode = true;
3099                         else
3100                                 is_unicode = false;
3101
3102                         /* BB FIXME investigate remapping reserved chars here */
3103                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3104                                         count, is_unicode, nls_codepage);
3105                         if (!*symlinkinfo)
3106                                 rc = -ENOMEM;
3107                 }
3108         }
3109         cifs_buf_release(pSMB);
3110         if (rc == -EAGAIN)
3111                 goto querySymLinkRetry;
3112         return rc;
3113 }
3114
3115 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3116 /*
3117  *      Recent Windows versions now create symlinks more frequently
3118  *      and they use the "reparse point" mechanism below.  We can of course
3119  *      do symlinks nicely to Samba and other servers which support the
3120  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3121  *      "MF" symlinks optionally, but for recent Windows we really need to
3122  *      reenable the code below and fix the cifs_symlink callers to handle this.
3123  *      In the interim this code has been moved to its own config option so
3124  *      it is not compiled in by default until callers fixed up and more tested.
3125  */
3126 int
3127 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3128                         const unsigned char *searchName,
3129                         char *symlinkinfo, const int buflen, __u16 fid,
3130                         const struct nls_table *nls_codepage)
3131 {
3132         int rc = 0;
3133         int bytes_returned;
3134         struct smb_com_transaction_ioctl_req *pSMB;
3135         struct smb_com_transaction_ioctl_rsp *pSMBr;
3136
3137         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3138         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3139                       (void **) &pSMBr);
3140         if (rc)
3141                 return rc;
3142
3143         pSMB->TotalParameterCount = 0 ;
3144         pSMB->TotalDataCount = 0;
3145         pSMB->MaxParameterCount = cpu_to_le32(2);
3146         /* BB find exact data count max from sess structure BB */
3147         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3148         pSMB->MaxSetupCount = 4;
3149         pSMB->Reserved = 0;
3150         pSMB->ParameterOffset = 0;
3151         pSMB->DataCount = 0;
3152         pSMB->DataOffset = 0;
3153         pSMB->SetupCount = 4;
3154         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3155         pSMB->ParameterCount = pSMB->TotalParameterCount;
3156         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3157         pSMB->IsFsctl = 1; /* FSCTL */
3158         pSMB->IsRootFlag = 0;
3159         pSMB->Fid = fid; /* file handle always le */
3160         pSMB->ByteCount = 0;
3161
3162         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3163                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3164         if (rc) {
3165                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3166         } else {                /* decode response */
3167                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3168                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3169                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3170                         /* BB also check enough total bytes returned */
3171                         rc = -EIO;      /* bad smb */
3172                         goto qreparse_out;
3173                 }
3174                 if (data_count && (data_count < 2048)) {
3175                         char *end_of_smb = 2 /* sizeof byte count */ +
3176                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3177
3178                         struct reparse_data *reparse_buf =
3179                                                 (struct reparse_data *)
3180                                                 ((char *)&pSMBr->hdr.Protocol
3181                                                                  + data_offset);
3182                         if ((char *)reparse_buf >= end_of_smb) {
3183                                 rc = -EIO;
3184                                 goto qreparse_out;
3185                         }
3186                         if ((reparse_buf->LinkNamesBuf +
3187                                 reparse_buf->TargetNameOffset +
3188                                 reparse_buf->TargetNameLen) > end_of_smb) {
3189                                 cFYI(1, "reparse buf beyond SMB");
3190                                 rc = -EIO;
3191                                 goto qreparse_out;
3192                         }
3193
3194                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3195                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3196                                                 (reparse_buf->LinkNamesBuf +
3197                                                 reparse_buf->TargetNameOffset),
3198                                                 buflen,
3199                                                 reparse_buf->TargetNameLen,
3200                                                 nls_codepage, 0);
3201                         } else { /* ASCII names */
3202                                 strncpy(symlinkinfo,
3203                                         reparse_buf->LinkNamesBuf +
3204                                         reparse_buf->TargetNameOffset,
3205                                         min_t(const int, buflen,
3206                                            reparse_buf->TargetNameLen));
3207                         }
3208                 } else {
3209                         rc = -EIO;
3210                         cFYI(1, "Invalid return data count on "
3211                                  "get reparse info ioctl");
3212                 }
3213                 symlinkinfo[buflen] = 0; /* just in case so the caller
3214                                         does not go off the end of the buffer */
3215                 cFYI(1, "readlink result - %s", symlinkinfo);
3216         }
3217
3218 qreparse_out:
3219         cifs_buf_release(pSMB);
3220
3221         /* Note: On -EAGAIN error only caller can retry on handle based calls
3222                 since file handle passed in no longer valid */
3223
3224         return rc;
3225 }
3226 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3227
3228 #ifdef CONFIG_CIFS_POSIX
3229
3230 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3231 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3232                              struct cifs_posix_ace *cifs_ace)
3233 {
3234         /* u8 cifs fields do not need le conversion */
3235         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3236         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3237         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3238         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3239
3240         return;
3241 }
3242
3243 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3244 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3245                                const int acl_type, const int size_of_data_area)
3246 {
3247         int size =  0;
3248         int i;
3249         __u16 count;
3250         struct cifs_posix_ace *pACE;
3251         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3252         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3253
3254         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3255                 return -EOPNOTSUPP;
3256
3257         if (acl_type & ACL_TYPE_ACCESS) {
3258                 count = le16_to_cpu(cifs_acl->access_entry_count);
3259                 pACE = &cifs_acl->ace_array[0];
3260                 size = sizeof(struct cifs_posix_acl);
3261                 size += sizeof(struct cifs_posix_ace) * count;
3262                 /* check if we would go beyond end of SMB */
3263                 if (size_of_data_area < size) {
3264                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3265                                 size_of_data_area, size);
3266                         return -EINVAL;
3267                 }
3268         } else if (acl_type & ACL_TYPE_DEFAULT) {
3269                 count = le16_to_cpu(cifs_acl->access_entry_count);
3270                 size = sizeof(struct cifs_posix_acl);
3271                 size += sizeof(struct cifs_posix_ace) * count;
3272 /* skip past access ACEs to get to default ACEs */
3273                 pACE = &cifs_acl->ace_array[count];
3274                 count = le16_to_cpu(cifs_acl->default_entry_count);
3275                 size += sizeof(struct cifs_posix_ace) * count;
3276                 /* check if we would go beyond end of SMB */
3277                 if (size_of_data_area < size)
3278                         return -EINVAL;
3279         } else {
3280                 /* illegal type */
3281                 return -EINVAL;
3282         }
3283
3284         size = posix_acl_xattr_size(count);
3285         if ((buflen == 0) || (local_acl == NULL)) {
3286                 /* used to query ACL EA size */
3287         } else if (size > buflen) {
3288                 return -ERANGE;
3289         } else /* buffer big enough */ {
3290                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3291                 for (i = 0; i < count ; i++) {
3292                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3293                         pACE++;
3294                 }
3295         }
3296         return size;
3297 }
3298
3299 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3300                                      const posix_acl_xattr_entry *local_ace)
3301 {
3302         __u16 rc = 0; /* 0 = ACL converted ok */
3303
3304         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3305         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3306         /* BB is there a better way to handle the large uid? */
3307         if (local_ace->e_id == cpu_to_le32(-1)) {
3308         /* Probably no need to le convert -1 on any arch but can not hurt */
3309                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3310         } else
3311                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3312         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3313         return rc;
3314 }
3315
3316 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3317 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3318                                const int buflen, const int acl_type)
3319 {
3320         __u16 rc = 0;
3321         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3322         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3323         int count;
3324         int i;
3325
3326         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3327                 return 0;
3328
3329         count = posix_acl_xattr_count((size_t)buflen);
3330         cFYI(1, "setting acl with %d entries from buf of length %d and "
3331                 "version of %d",
3332                 count, buflen, le32_to_cpu(local_acl->a_version));
3333         if (le32_to_cpu(local_acl->a_version) != 2) {
3334                 cFYI(1, "unknown POSIX ACL version %d",
3335                      le32_to_cpu(local_acl->a_version));
3336                 return 0;
3337         }
3338         cifs_acl->version = cpu_to_le16(1);
3339         if (acl_type == ACL_TYPE_ACCESS)
3340                 cifs_acl->access_entry_count = cpu_to_le16(count);
3341         else if (acl_type == ACL_TYPE_DEFAULT)
3342                 cifs_acl->default_entry_count = cpu_to_le16(count);
3343         else {
3344                 cFYI(1, "unknown ACL type %d", acl_type);
3345                 return 0;
3346         }
3347         for (i = 0; i < count; i++) {
3348                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3349                                         &local_acl->a_entries[i]);
3350                 if (rc != 0) {
3351                         /* ACE not converted */
3352                         break;
3353                 }
3354         }
3355         if (rc == 0) {
3356                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3357                 rc += sizeof(struct cifs_posix_acl);
3358                 /* BB add check to make sure ACL does not overflow SMB */
3359         }
3360         return rc;
3361 }
3362
3363 int
3364 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3365                    const unsigned char *searchName,
3366                    char *acl_inf, const int buflen, const int acl_type,
3367                    const struct nls_table *nls_codepage, int remap)
3368 {
3369 /* SMB_QUERY_POSIX_ACL */
3370         TRANSACTION2_QPI_REQ *pSMB = NULL;
3371         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3372         int rc = 0;
3373         int bytes_returned;
3374         int name_len;
3375         __u16 params, byte_count;
3376
3377         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3378
3379 queryAclRetry:
3380         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3381                 (void **) &pSMBr);
3382         if (rc)
3383                 return rc;
3384
3385         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3386                 name_len =
3387                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3388                                            searchName, PATH_MAX, nls_codepage,
3389                                            remap);
3390                 name_len++;     /* trailing null */
3391                 name_len *= 2;
3392                 pSMB->FileName[name_len] = 0;
3393                 pSMB->FileName[name_len+1] = 0;
3394         } else {        /* BB improve the check for buffer overruns BB */
3395                 name_len = strnlen(searchName, PATH_MAX);
3396                 name_len++;     /* trailing null */
3397                 strncpy(pSMB->FileName, searchName, name_len);
3398         }
3399
3400         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3401         pSMB->TotalDataCount = 0;
3402         pSMB->MaxParameterCount = cpu_to_le16(2);
3403         /* BB find exact max data count below from sess structure BB */
3404         pSMB->MaxDataCount = cpu_to_le16(4000);
3405         pSMB->MaxSetupCount = 0;
3406         pSMB->Reserved = 0;
3407         pSMB->Flags = 0;
3408         pSMB->Timeout = 0;
3409         pSMB->Reserved2 = 0;
3410         pSMB->ParameterOffset = cpu_to_le16(
3411                 offsetof(struct smb_com_transaction2_qpi_req,
3412                          InformationLevel) - 4);
3413         pSMB->DataCount = 0;
3414         pSMB->DataOffset = 0;
3415         pSMB->SetupCount = 1;
3416         pSMB->Reserved3 = 0;
3417         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3418         byte_count = params + 1 /* pad */ ;
3419         pSMB->TotalParameterCount = cpu_to_le16(params);
3420         pSMB->ParameterCount = pSMB->TotalParameterCount;
3421         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3422         pSMB->Reserved4 = 0;
3423         inc_rfc1001_len(pSMB, byte_count);
3424         pSMB->ByteCount = cpu_to_le16(byte_count);
3425
3426         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3427                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3428         cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3429         if (rc) {
3430                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3431         } else {
3432                 /* decode response */
3433
3434                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3435                 /* BB also check enough total bytes returned */
3436                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3437                         rc = -EIO;      /* bad smb */
3438                 else {
3439                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3440                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3441                         rc = cifs_copy_posix_acl(acl_inf,
3442                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3443                                 buflen, acl_type, count);
3444                 }
3445         }
3446         cifs_buf_release(pSMB);
3447         if (rc == -EAGAIN)
3448                 goto queryAclRetry;
3449         return rc;
3450 }
3451
3452 int
3453 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3454                    const unsigned char *fileName,
3455                    const char *local_acl, const int buflen,
3456                    const int acl_type,
3457                    const struct nls_table *nls_codepage, int remap)
3458 {
3459         struct smb_com_transaction2_spi_req *pSMB = NULL;
3460         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3461         char *parm_data;
3462         int name_len;
3463         int rc = 0;
3464         int bytes_returned = 0;
3465         __u16 params, byte_count, data_count, param_offset, offset;
3466
3467         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3468 setAclRetry:
3469         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3470                       (void **) &pSMBr);
3471         if (rc)
3472                 return rc;
3473         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3474                 name_len =
3475                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3476                                            PATH_MAX, nls_codepage, remap);
3477                 name_len++;     /* trailing null */
3478                 name_len *= 2;
3479         } else {        /* BB improve the check for buffer overruns BB */
3480                 name_len = strnlen(fileName, PATH_MAX);
3481                 name_len++;     /* trailing null */
3482                 strncpy(pSMB->FileName, fileName, name_len);
3483         }
3484         params = 6 + name_len;
3485         pSMB->MaxParameterCount = cpu_to_le16(2);
3486         /* BB find max SMB size from sess */
3487         pSMB->MaxDataCount = cpu_to_le16(1000);
3488         pSMB->MaxSetupCount = 0;
3489         pSMB->Reserved = 0;
3490         pSMB->Flags = 0;
3491         pSMB->Timeout = 0;
3492         pSMB->Reserved2 = 0;
3493         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3494                                 InformationLevel) - 4;
3495         offset = param_offset + params;
3496         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3497         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3498
3499         /* convert to on the wire format for POSIX ACL */
3500         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3501
3502         if (data_count == 0) {
3503                 rc = -EOPNOTSUPP;
3504                 goto setACLerrorExit;
3505         }
3506         pSMB->DataOffset = cpu_to_le16(offset);
3507         pSMB->SetupCount = 1;
3508         pSMB->Reserved3 = 0;
3509         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3510         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3511         byte_count = 3 /* pad */  + params + data_count;
3512         pSMB->DataCount = cpu_to_le16(data_count);
3513         pSMB->TotalDataCount = pSMB->DataCount;
3514         pSMB->ParameterCount = cpu_to_le16(params);
3515         pSMB->TotalParameterCount = pSMB->ParameterCount;
3516         pSMB->Reserved4 = 0;
3517         inc_rfc1001_len(pSMB, byte_count);
3518         pSMB->ByteCount = cpu_to_le16(byte_count);
3519         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3520                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3521         if (rc)
3522                 cFYI(1, "Set POSIX ACL returned %d", rc);
3523
3524 setACLerrorExit:
3525         cifs_buf_release(pSMB);
3526         if (rc == -EAGAIN)
3527                 goto setAclRetry;
3528         return rc;
3529 }
3530
3531 /* BB fix tabs in this function FIXME BB */
3532 int
3533 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3534                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3535 {
3536         int rc = 0;
3537         struct smb_t2_qfi_req *pSMB = NULL;
3538         struct smb_t2_qfi_rsp *pSMBr = NULL;
3539         int bytes_returned;
3540         __u16 params, byte_count;
3541
3542         cFYI(1, "In GetExtAttr");
3543         if (tcon == NULL)
3544                 return -ENODEV;
3545
3546 GetExtAttrRetry:
3547         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3548                         (void **) &pSMBr);
3549         if (rc)
3550                 return rc;
3551
3552         params = 2 /* level */ + 2 /* fid */;
3553         pSMB->t2.TotalDataCount = 0;
3554         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3555         /* BB find exact max data count below from sess structure BB */
3556         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3557         pSMB->t2.MaxSetupCount = 0;
3558         pSMB->t2.Reserved = 0;
3559         pSMB->t2.Flags = 0;
3560         pSMB->t2.Timeout = 0;
3561         pSMB->t2.Reserved2 = 0;
3562         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3563                                                Fid) - 4);
3564         pSMB->t2.DataCount = 0;
3565         pSMB->t2.DataOffset = 0;
3566         pSMB->t2.SetupCount = 1;
3567         pSMB->t2.Reserved3 = 0;
3568         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3569         byte_count = params + 1 /* pad */ ;
3570         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3571         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3572         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3573         pSMB->Pad = 0;
3574         pSMB->Fid = netfid;
3575         inc_rfc1001_len(pSMB, byte_count);
3576         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3577
3578         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3579                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3580         if (rc) {
3581                 cFYI(1, "error %d in GetExtAttr", rc);
3582         } else {
3583                 /* decode response */
3584                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3585                 /* BB also check enough total bytes returned */
3586                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3587                         /* If rc should we check for EOPNOSUPP and
3588                            disable the srvino flag? or in caller? */
3589                         rc = -EIO;      /* bad smb */
3590                 else {
3591                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3592                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3593                         struct file_chattr_info *pfinfo;
3594                         /* BB Do we need a cast or hash here ? */
3595                         if (count != 16) {
3596                                 cFYI(1, "Illegal size ret in GetExtAttr");
3597                                 rc = -EIO;
3598                                 goto GetExtAttrOut;
3599                         }
3600                         pfinfo = (struct file_chattr_info *)
3601                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3602                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3603                         *pMask = le64_to_cpu(pfinfo->mask);
3604                 }
3605         }
3606 GetExtAttrOut:
3607         cifs_buf_release(pSMB);
3608         if (rc == -EAGAIN)
3609                 goto GetExtAttrRetry;
3610         return rc;
3611 }
3612
3613 #endif /* CONFIG_POSIX */
3614
3615 #ifdef CONFIG_CIFS_ACL
3616 /*
3617  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3618  * all NT TRANSACTS that we init here have total parm and data under about 400
3619  * bytes (to fit in small cifs buffer size), which is the case so far, it
3620  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3621  * returned setup area) and MaxParameterCount (returned parms size) must be set
3622  * by caller
3623  */
3624 static int
3625 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3626                    const int parm_len, struct cifs_tcon *tcon,
3627                    void **ret_buf)
3628 {
3629         int rc;
3630         __u32 temp_offset;
3631         struct smb_com_ntransact_req *pSMB;
3632
3633         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3634                                 (void **)&pSMB);
3635         if (rc)
3636                 return rc;
3637         *ret_buf = (void *)pSMB;
3638         pSMB->Reserved = 0;
3639         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3640         pSMB->TotalDataCount  = 0;
3641         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3642         pSMB->ParameterCount = pSMB->TotalParameterCount;
3643         pSMB->DataCount  = pSMB->TotalDataCount;
3644         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3645                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3646         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3647         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3648         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3649         pSMB->SubCommand = cpu_to_le16(sub_command);
3650         return 0;
3651 }
3652
3653 static int
3654 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3655                    __u32 *pparmlen, __u32 *pdatalen)
3656 {
3657         char *end_of_smb;
3658         __u32 data_count, data_offset, parm_count, parm_offset;
3659         struct smb_com_ntransact_rsp *pSMBr;
3660         u16 bcc;
3661
3662         *pdatalen = 0;
3663         *pparmlen = 0;
3664
3665         if (buf == NULL)
3666                 return -EINVAL;
3667
3668         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3669
3670         bcc = get_bcc(&pSMBr->hdr);
3671         end_of_smb = 2 /* sizeof byte count */ + bcc +
3672                         (char *)&pSMBr->ByteCount;
3673
3674         data_offset = le32_to_cpu(pSMBr->DataOffset);
3675         data_count = le32_to_cpu(pSMBr->DataCount);
3676         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3677         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3678
3679         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3680         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3681
3682         /* should we also check that parm and data areas do not overlap? */
3683         if (*ppparm > end_of_smb) {
3684                 cFYI(1, "parms start after end of smb");
3685                 return -EINVAL;
3686         } else if (parm_count + *ppparm > end_of_smb) {
3687                 cFYI(1, "parm end after end of smb");
3688                 return -EINVAL;
3689         } else if (*ppdata > end_of_smb) {
3690                 cFYI(1, "data starts after end of smb");
3691                 return -EINVAL;
3692         } else if (data_count + *ppdata > end_of_smb) {
3693                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3694                         *ppdata, data_count, (data_count + *ppdata),
3695                         end_of_smb, pSMBr);
3696                 return -EINVAL;
3697         } else if (parm_count + data_count > bcc) {
3698                 cFYI(1, "parm count and data count larger than SMB");
3699                 return -EINVAL;
3700         }
3701         *pdatalen = data_count;
3702         *pparmlen = parm_count;
3703         return 0;
3704 }
3705
3706 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3707 int
3708 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3709                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3710 {
3711         int rc = 0;
3712         int buf_type = 0;
3713         QUERY_SEC_DESC_REQ *pSMB;
3714         struct kvec iov[1];
3715
3716         cFYI(1, "GetCifsACL");
3717
3718         *pbuflen = 0;
3719         *acl_inf = NULL;
3720
3721         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3722                         8 /* parm len */, tcon, (void **) &pSMB);
3723         if (rc)
3724                 return rc;
3725
3726         pSMB->MaxParameterCount = cpu_to_le32(4);
3727         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3728         pSMB->MaxSetupCount = 0;
3729         pSMB->Fid = fid; /* file handle always le */
3730         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3731                                      CIFS_ACL_DACL);
3732         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3733         inc_rfc1001_len(pSMB, 11);
3734         iov[0].iov_base = (char *)pSMB;
3735         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3736
3737         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3738                          0);
3739         cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3740         if (rc) {
3741                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3742         } else {                /* decode response */
3743                 __le32 *parm;
3744                 __u32 parm_len;
3745                 __u32 acl_len;
3746                 struct smb_com_ntransact_rsp *pSMBr;
3747                 char *pdata;
3748
3749 /* validate_nttransact */
3750                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3751                                         &pdata, &parm_len, pbuflen);
3752                 if (rc)
3753                         goto qsec_out;
3754                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3755
3756                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3757
3758                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3759                         rc = -EIO;      /* bad smb */
3760                         *pbuflen = 0;
3761                         goto qsec_out;
3762                 }
3763
3764 /* BB check that data area is minimum length and as big as acl_len */
3765
3766                 acl_len = le32_to_cpu(*parm);
3767                 if (acl_len != *pbuflen) {
3768                         cERROR(1, "acl length %d does not match %d",
3769                                    acl_len, *pbuflen);
3770                         if (*pbuflen > acl_len)
3771                                 *pbuflen = acl_len;
3772                 }
3773
3774                 /* check if buffer is big enough for the acl
3775                    header followed by the smallest SID */
3776                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3777                     (*pbuflen >= 64 * 1024)) {
3778                         cERROR(1, "bad acl length %d", *pbuflen);
3779                         rc = -EINVAL;
3780                         *pbuflen = 0;
3781                 } else {
3782                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3783                         if (*acl_inf == NULL) {
3784                                 *pbuflen = 0;
3785                                 rc = -ENOMEM;
3786                         }
3787                         memcpy(*acl_inf, pdata, *pbuflen);
3788                 }
3789         }
3790 qsec_out:
3791         if (buf_type == CIFS_SMALL_BUFFER)
3792                 cifs_small_buf_release(iov[0].iov_base);
3793         else if (buf_type == CIFS_LARGE_BUFFER)
3794                 cifs_buf_release(iov[0].iov_base);
3795 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3796         return rc;
3797 }
3798
3799 int
3800 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3801                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3802 {
3803         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3804         int rc = 0;
3805         int bytes_returned = 0;
3806         SET_SEC_DESC_REQ *pSMB = NULL;
3807         void *pSMBr;
3808
3809 setCifsAclRetry:
3810         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3811         if (rc)
3812                 return rc;
3813
3814         pSMB->MaxSetupCount = 0;
3815         pSMB->Reserved = 0;
3816
3817         param_count = 8;
3818         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3819         data_count = acllen;
3820         data_offset = param_offset + param_count;
3821         byte_count = 3 /* pad */  + param_count;
3822
3823         pSMB->DataCount = cpu_to_le32(data_count);
3824         pSMB->TotalDataCount = pSMB->DataCount;
3825         pSMB->MaxParameterCount = cpu_to_le32(4);
3826         pSMB->MaxDataCount = cpu_to_le32(16384);
3827         pSMB->ParameterCount = cpu_to_le32(param_count);
3828         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3829         pSMB->TotalParameterCount = pSMB->ParameterCount;
3830         pSMB->DataOffset = cpu_to_le32(data_offset);
3831         pSMB->SetupCount = 0;
3832         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3833         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3834
3835         pSMB->Fid = fid; /* file handle always le */
3836         pSMB->Reserved2 = 0;
3837         pSMB->AclFlags = cpu_to_le32(aclflag);
3838
3839         if (pntsd && acllen) {
3840                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3841                                 data_offset, pntsd, acllen);
3842                 inc_rfc1001_len(pSMB, byte_count + data_count);
3843         } else
3844                 inc_rfc1001_len(pSMB, byte_count);
3845
3846         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3847                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3848
3849         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3850         if (rc)
3851                 cFYI(1, "Set CIFS ACL returned %d", rc);
3852         cifs_buf_release(pSMB);
3853
3854         if (rc == -EAGAIN)
3855                 goto setCifsAclRetry;
3856
3857         return (rc);
3858 }
3859
3860 #endif /* CONFIG_CIFS_ACL */
3861
3862 /* Legacy Query Path Information call for lookup to old servers such
3863    as Win9x/WinME */
3864 int
3865 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3866                     const char *search_name, FILE_ALL_INFO *data,
3867                     const struct nls_table *nls_codepage, int remap)
3868 {
3869         QUERY_INFORMATION_REQ *pSMB;
3870         QUERY_INFORMATION_RSP *pSMBr;
3871         int rc = 0;
3872         int bytes_returned;
3873         int name_len;
3874
3875         cFYI(1, "In SMBQPath path %s", search_name);
3876 QInfRetry:
3877         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3878                       (void **) &pSMBr);
3879         if (rc)
3880                 return rc;
3881
3882         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3883                 name_len =
3884                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3885                                            search_name, PATH_MAX, nls_codepage,
3886                                            remap);
3887                 name_len++;     /* trailing null */
3888                 name_len *= 2;
3889         } else {
3890                 name_len = strnlen(search_name, PATH_MAX);
3891                 name_len++;     /* trailing null */
3892                 strncpy(pSMB->FileName, search_name, name_len);
3893         }
3894         pSMB->BufferFormat = 0x04;
3895         name_len++; /* account for buffer type byte */
3896         inc_rfc1001_len(pSMB, (__u16)name_len);
3897         pSMB->ByteCount = cpu_to_le16(name_len);
3898
3899         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3900                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3901         if (rc) {
3902                 cFYI(1, "Send error in QueryInfo = %d", rc);
3903         } else if (data) {
3904                 struct timespec ts;
3905                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3906
3907                 /* decode response */
3908                 /* BB FIXME - add time zone adjustment BB */
3909                 memset(data, 0, sizeof(FILE_ALL_INFO));
3910                 ts.tv_nsec = 0;
3911                 ts.tv_sec = time;
3912                 /* decode time fields */
3913                 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3914                 data->LastWriteTime = data->ChangeTime;
3915                 data->LastAccessTime = 0;
3916                 data->AllocationSize =
3917                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3918                 data->EndOfFile = data->AllocationSize;
3919                 data->Attributes =
3920                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3921         } else
3922                 rc = -EIO; /* bad buffer passed in */
3923
3924         cifs_buf_release(pSMB);
3925
3926         if (rc == -EAGAIN)
3927                 goto QInfRetry;
3928
3929         return rc;
3930 }
3931
3932 int
3933 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3934                  u16 netfid, FILE_ALL_INFO *pFindData)
3935 {
3936         struct smb_t2_qfi_req *pSMB = NULL;
3937         struct smb_t2_qfi_rsp *pSMBr = NULL;
3938         int rc = 0;
3939         int bytes_returned;
3940         __u16 params, byte_count;
3941
3942 QFileInfoRetry:
3943         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3944                       (void **) &pSMBr);
3945         if (rc)
3946                 return rc;
3947
3948         params = 2 /* level */ + 2 /* fid */;
3949         pSMB->t2.TotalDataCount = 0;
3950         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3951         /* BB find exact max data count below from sess structure BB */
3952         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3953         pSMB->t2.MaxSetupCount = 0;
3954         pSMB->t2.Reserved = 0;
3955         pSMB->t2.Flags = 0;
3956         pSMB->t2.Timeout = 0;
3957         pSMB->t2.Reserved2 = 0;
3958         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3959                                                Fid) - 4);
3960         pSMB->t2.DataCount = 0;
3961         pSMB->t2.DataOffset = 0;
3962         pSMB->t2.SetupCount = 1;
3963         pSMB->t2.Reserved3 = 0;
3964         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3965         byte_count = params + 1 /* pad */ ;
3966         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3967         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3968         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3969         pSMB->Pad = 0;
3970         pSMB->Fid = netfid;
3971         inc_rfc1001_len(pSMB, byte_count);
3972
3973         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3974                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3975         if (rc) {
3976                 cFYI(1, "Send error in QPathInfo = %d", rc);
3977         } else {                /* decode response */
3978                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3979
3980                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3981                         rc = -EIO;
3982                 else if (get_bcc(&pSMBr->hdr) < 40)
3983                         rc = -EIO;      /* bad smb */
3984                 else if (pFindData) {
3985                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3986                         memcpy((char *) pFindData,
3987                                (char *) &pSMBr->hdr.Protocol +
3988                                data_offset, sizeof(FILE_ALL_INFO));
3989                 } else
3990                     rc = -ENOMEM;
3991         }
3992         cifs_buf_release(pSMB);
3993         if (rc == -EAGAIN)
3994                 goto QFileInfoRetry;
3995
3996         return rc;
3997 }
3998
3999 int
4000 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4001                  const char *search_name, FILE_ALL_INFO *data,
4002                  int legacy /* old style infolevel */,
4003                  const struct nls_table *nls_codepage, int remap)
4004 {
4005         /* level 263 SMB_QUERY_FILE_ALL_INFO */
4006         TRANSACTION2_QPI_REQ *pSMB = NULL;
4007         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4008         int rc = 0;
4009         int bytes_returned;
4010         int name_len;
4011         __u16 params, byte_count;
4012
4013         /* cFYI(1, "In QPathInfo path %s", search_name); */
4014 QPathInfoRetry:
4015         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4016                       (void **) &pSMBr);
4017         if (rc)
4018                 return rc;
4019
4020         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4021                 name_len =
4022                     cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4023                                        PATH_MAX, nls_codepage, remap);
4024                 name_len++;     /* trailing null */
4025                 name_len *= 2;
4026         } else {        /* BB improve the check for buffer overruns BB */
4027                 name_len = strnlen(search_name, PATH_MAX);
4028                 name_len++;     /* trailing null */
4029                 strncpy(pSMB->FileName, search_name, name_len);
4030         }
4031
4032         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4033         pSMB->TotalDataCount = 0;
4034         pSMB->MaxParameterCount = cpu_to_le16(2);
4035         /* BB find exact max SMB PDU from sess structure BB */
4036         pSMB->MaxDataCount = cpu_to_le16(4000);
4037         pSMB->MaxSetupCount = 0;
4038         pSMB->Reserved = 0;
4039         pSMB->Flags = 0;
4040         pSMB->Timeout = 0;
4041         pSMB->Reserved2 = 0;
4042         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4043         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4044         pSMB->DataCount = 0;
4045         pSMB->DataOffset = 0;
4046         pSMB->SetupCount = 1;
4047         pSMB->Reserved3 = 0;
4048         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4049         byte_count = params + 1 /* pad */ ;
4050         pSMB->TotalParameterCount = cpu_to_le16(params);
4051         pSMB->ParameterCount = pSMB->TotalParameterCount;
4052         if (legacy)
4053                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4054         else
4055                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4056         pSMB->Reserved4 = 0;
4057         inc_rfc1001_len(pSMB, byte_count);
4058         pSMB->ByteCount = cpu_to_le16(byte_count);
4059
4060         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4061                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4062         if (rc) {
4063                 cFYI(1, "Send error in QPathInfo = %d", rc);
4064         } else {                /* decode response */
4065                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4066
4067                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4068                         rc = -EIO;
4069                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4070                         rc = -EIO;      /* bad smb */
4071                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4072                         rc = -EIO;  /* 24 or 26 expected but we do not read
4073                                         last field */
4074                 else if (data) {
4075                         int size;
4076                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4077
4078                         /*
4079                          * On legacy responses we do not read the last field,
4080                          * EAsize, fortunately since it varies by subdialect and
4081                          * also note it differs on Set vs Get, ie two bytes or 4
4082                          * bytes depending but we don't care here.
4083                          */
4084                         if (legacy)
4085                                 size = sizeof(FILE_INFO_STANDARD);
4086                         else
4087                                 size = sizeof(FILE_ALL_INFO);
4088                         memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4089                                data_offset, size);
4090                 } else
4091                     rc = -ENOMEM;
4092         }
4093         cifs_buf_release(pSMB);
4094         if (rc == -EAGAIN)
4095                 goto QPathInfoRetry;
4096
4097         return rc;
4098 }
4099
4100 int
4101 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4102                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4103 {
4104         struct smb_t2_qfi_req *pSMB = NULL;
4105         struct smb_t2_qfi_rsp *pSMBr = NULL;
4106         int rc = 0;
4107         int bytes_returned;
4108         __u16 params, byte_count;
4109
4110 UnixQFileInfoRetry:
4111         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4112                       (void **) &pSMBr);
4113         if (rc)
4114                 return rc;
4115
4116         params = 2 /* level */ + 2 /* fid */;
4117         pSMB->t2.TotalDataCount = 0;
4118         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4119         /* BB find exact max data count below from sess structure BB */
4120         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4121         pSMB->t2.MaxSetupCount = 0;
4122         pSMB->t2.Reserved = 0;
4123         pSMB->t2.Flags = 0;
4124         pSMB->t2.Timeout = 0;
4125         pSMB->t2.Reserved2 = 0;
4126         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4127                                                Fid) - 4);
4128         pSMB->t2.DataCount = 0;
4129         pSMB->t2.DataOffset = 0;
4130         pSMB->t2.SetupCount = 1;
4131         pSMB->t2.Reserved3 = 0;
4132         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4133         byte_count = params + 1 /* pad */ ;
4134         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4135         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4136         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4137         pSMB->Pad = 0;
4138         pSMB->Fid = netfid;
4139         inc_rfc1001_len(pSMB, byte_count);
4140
4141         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4142                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4143         if (rc) {
4144                 cFYI(1, "Send error in QPathInfo = %d", rc);
4145         } else {                /* decode response */
4146                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4147
4148                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4149                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4150                                    "Unix Extensions can be disabled on mount "
4151                                    "by specifying the nosfu mount option.");
4152                         rc = -EIO;      /* bad smb */
4153                 } else {
4154                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4155                         memcpy((char *) pFindData,
4156                                (char *) &pSMBr->hdr.Protocol +
4157                                data_offset,
4158                                sizeof(FILE_UNIX_BASIC_INFO));
4159                 }
4160         }
4161
4162         cifs_buf_release(pSMB);
4163         if (rc == -EAGAIN)
4164                 goto UnixQFileInfoRetry;
4165
4166         return rc;
4167 }
4168
4169 int
4170 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4171                      const unsigned char *searchName,
4172                      FILE_UNIX_BASIC_INFO *pFindData,
4173                      const struct nls_table *nls_codepage, int remap)
4174 {
4175 /* SMB_QUERY_FILE_UNIX_BASIC */
4176         TRANSACTION2_QPI_REQ *pSMB = NULL;
4177         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4178         int rc = 0;
4179         int bytes_returned = 0;
4180         int name_len;
4181         __u16 params, byte_count;
4182
4183         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4184 UnixQPathInfoRetry:
4185         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4186                       (void **) &pSMBr);
4187         if (rc)
4188                 return rc;
4189
4190         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4191                 name_len =
4192                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4193                                        PATH_MAX, nls_codepage, remap);
4194                 name_len++;     /* trailing null */
4195                 name_len *= 2;
4196         } else {        /* BB improve the check for buffer overruns BB */
4197                 name_len = strnlen(searchName, PATH_MAX);
4198                 name_len++;     /* trailing null */
4199                 strncpy(pSMB->FileName, searchName, name_len);
4200         }
4201
4202         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4203         pSMB->TotalDataCount = 0;
4204         pSMB->MaxParameterCount = cpu_to_le16(2);
4205         /* BB find exact max SMB PDU from sess structure BB */
4206         pSMB->MaxDataCount = cpu_to_le16(4000);
4207         pSMB->MaxSetupCount = 0;
4208         pSMB->Reserved = 0;
4209         pSMB->Flags = 0;
4210         pSMB->Timeout = 0;
4211         pSMB->Reserved2 = 0;
4212         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4213         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4214         pSMB->DataCount = 0;
4215         pSMB->DataOffset = 0;
4216         pSMB->SetupCount = 1;
4217         pSMB->Reserved3 = 0;
4218         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4219         byte_count = params + 1 /* pad */ ;
4220         pSMB->TotalParameterCount = cpu_to_le16(params);
4221         pSMB->ParameterCount = pSMB->TotalParameterCount;
4222         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4223         pSMB->Reserved4 = 0;
4224         inc_rfc1001_len(pSMB, byte_count);
4225         pSMB->ByteCount = cpu_to_le16(byte_count);
4226
4227         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4228                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4229         if (rc) {
4230                 cFYI(1, "Send error in QPathInfo = %d", rc);
4231         } else {                /* decode response */
4232                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4233
4234                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4235                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4236                                    "Unix Extensions can be disabled on mount "
4237                                    "by specifying the nosfu mount option.");
4238                         rc = -EIO;      /* bad smb */
4239                 } else {
4240                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4241                         memcpy((char *) pFindData,
4242                                (char *) &pSMBr->hdr.Protocol +
4243                                data_offset,
4244                                sizeof(FILE_UNIX_BASIC_INFO));
4245                 }
4246         }
4247         cifs_buf_release(pSMB);
4248         if (rc == -EAGAIN)
4249                 goto UnixQPathInfoRetry;
4250
4251         return rc;
4252 }
4253
4254 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4255 int
4256 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4257               const char *searchName,
4258               const struct nls_table *nls_codepage,
4259               __u16 *pnetfid, __u16 search_flags,
4260               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4261 {
4262 /* level 257 SMB_ */
4263         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4264         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4265         T2_FFIRST_RSP_PARMS *parms;
4266         int rc = 0;
4267         int bytes_returned = 0;
4268         int name_len;
4269         __u16 params, byte_count;
4270
4271         cFYI(1, "In FindFirst for %s", searchName);
4272
4273 findFirstRetry:
4274         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4275                       (void **) &pSMBr);
4276         if (rc)
4277                 return rc;
4278
4279         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4280                 name_len =
4281                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4282                                        PATH_MAX, nls_codepage, remap);
4283                 /* We can not add the asterik earlier in case
4284                 it got remapped to 0xF03A as if it were part of the
4285                 directory name instead of a wildcard */
4286                 name_len *= 2;
4287                 pSMB->FileName[name_len] = dirsep;
4288                 pSMB->FileName[name_len+1] = 0;
4289                 pSMB->FileName[name_len+2] = '*';
4290                 pSMB->FileName[name_len+3] = 0;
4291                 name_len += 4; /* now the trailing null */
4292                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4293                 pSMB->FileName[name_len+1] = 0;
4294                 name_len += 2;
4295         } else {        /* BB add check for overrun of SMB buf BB */
4296                 name_len = strnlen(searchName, PATH_MAX);
4297 /* BB fix here and in unicode clause above ie
4298                 if (name_len > buffersize-header)
4299                         free buffer exit; BB */
4300                 strncpy(pSMB->FileName, searchName, name_len);
4301                 pSMB->FileName[name_len] = dirsep;
4302                 pSMB->FileName[name_len+1] = '*';
4303                 pSMB->FileName[name_len+2] = 0;
4304                 name_len += 3;
4305         }
4306
4307         params = 12 + name_len /* includes null */ ;
4308         pSMB->TotalDataCount = 0;       /* no EAs */
4309         pSMB->MaxParameterCount = cpu_to_le16(10);
4310         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4311         pSMB->MaxSetupCount = 0;
4312         pSMB->Reserved = 0;
4313         pSMB->Flags = 0;
4314         pSMB->Timeout = 0;
4315         pSMB->Reserved2 = 0;
4316         byte_count = params + 1 /* pad */ ;
4317         pSMB->TotalParameterCount = cpu_to_le16(params);
4318         pSMB->ParameterCount = pSMB->TotalParameterCount;
4319         pSMB->ParameterOffset = cpu_to_le16(
4320               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4321                 - 4);
4322         pSMB->DataCount = 0;
4323         pSMB->DataOffset = 0;
4324         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4325         pSMB->Reserved3 = 0;
4326         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4327         pSMB->SearchAttributes =
4328             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4329                         ATTR_DIRECTORY);
4330         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4331         pSMB->SearchFlags = cpu_to_le16(search_flags);
4332         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4333
4334         /* BB what should we set StorageType to? Does it matter? BB */
4335         pSMB->SearchStorageType = 0;
4336         inc_rfc1001_len(pSMB, byte_count);
4337         pSMB->ByteCount = cpu_to_le16(byte_count);
4338
4339         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4340                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4341         cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4342
4343         if (rc) {/* BB add logic to retry regular search if Unix search
4344                         rejected unexpectedly by server */
4345                 /* BB Add code to handle unsupported level rc */
4346                 cFYI(1, "Error in FindFirst = %d", rc);
4347
4348                 cifs_buf_release(pSMB);
4349
4350                 /* BB eventually could optimize out free and realloc of buf */
4351                 /*    for this case */
4352                 if (rc == -EAGAIN)
4353                         goto findFirstRetry;
4354         } else { /* decode response */
4355                 /* BB remember to free buffer if error BB */
4356                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4357                 if (rc == 0) {
4358                         unsigned int lnoff;
4359
4360                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4361                                 psrch_inf->unicode = true;
4362                         else
4363                                 psrch_inf->unicode = false;
4364
4365                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4366                         psrch_inf->smallBuf = 0;
4367                         psrch_inf->srch_entries_start =
4368                                 (char *) &pSMBr->hdr.Protocol +
4369                                         le16_to_cpu(pSMBr->t2.DataOffset);
4370                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4371                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4372
4373                         if (parms->EndofSearch)
4374                                 psrch_inf->endOfSearch = true;
4375                         else
4376                                 psrch_inf->endOfSearch = false;
4377
4378                         psrch_inf->entries_in_buffer =
4379                                         le16_to_cpu(parms->SearchCount);
4380                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4381                                 psrch_inf->entries_in_buffer;
4382                         lnoff = le16_to_cpu(parms->LastNameOffset);
4383                         if (CIFSMaxBufSize < lnoff) {
4384                                 cERROR(1, "ignoring corrupt resume name");
4385                                 psrch_inf->last_entry = NULL;
4386                                 return rc;
4387                         }
4388
4389                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4390                                                         lnoff;
4391
4392                         *pnetfid = parms->SearchHandle;
4393                 } else {
4394                         cifs_buf_release(pSMB);
4395                 }
4396         }
4397
4398         return rc;
4399 }
4400
4401 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4402                  __u16 searchHandle, __u16 search_flags,
4403                  struct cifs_search_info *psrch_inf)
4404 {
4405         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4406         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4407         T2_FNEXT_RSP_PARMS *parms;
4408         char *response_data;
4409         int rc = 0;
4410         int bytes_returned;
4411         unsigned int name_len;
4412         __u16 params, byte_count;
4413
4414         cFYI(1, "In FindNext");
4415
4416         if (psrch_inf->endOfSearch)
4417                 return -ENOENT;
4418
4419         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4420                 (void **) &pSMBr);
4421         if (rc)
4422                 return rc;
4423
4424         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4425         byte_count = 0;
4426         pSMB->TotalDataCount = 0;       /* no EAs */
4427         pSMB->MaxParameterCount = cpu_to_le16(8);
4428         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4429         pSMB->MaxSetupCount = 0;
4430         pSMB->Reserved = 0;
4431         pSMB->Flags = 0;
4432         pSMB->Timeout = 0;
4433         pSMB->Reserved2 = 0;
4434         pSMB->ParameterOffset =  cpu_to_le16(
4435               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4436         pSMB->DataCount = 0;
4437         pSMB->DataOffset = 0;
4438         pSMB->SetupCount = 1;
4439         pSMB->Reserved3 = 0;
4440         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4441         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4442         pSMB->SearchCount =
4443                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4444         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4445         pSMB->ResumeKey = psrch_inf->resume_key;
4446         pSMB->SearchFlags = cpu_to_le16(search_flags);
4447
4448         name_len = psrch_inf->resume_name_len;
4449         params += name_len;
4450         if (name_len < PATH_MAX) {
4451                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4452                 byte_count += name_len;
4453                 /* 14 byte parm len above enough for 2 byte null terminator */
4454                 pSMB->ResumeFileName[name_len] = 0;
4455                 pSMB->ResumeFileName[name_len+1] = 0;
4456         } else {
4457                 rc = -EINVAL;
4458                 goto FNext2_err_exit;
4459         }
4460         byte_count = params + 1 /* pad */ ;
4461         pSMB->TotalParameterCount = cpu_to_le16(params);
4462         pSMB->ParameterCount = pSMB->TotalParameterCount;
4463         inc_rfc1001_len(pSMB, byte_count);
4464         pSMB->ByteCount = cpu_to_le16(byte_count);
4465
4466         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4467                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4468         cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4469         if (rc) {
4470                 if (rc == -EBADF) {
4471                         psrch_inf->endOfSearch = true;
4472                         cifs_buf_release(pSMB);
4473                         rc = 0; /* search probably was closed at end of search*/
4474                 } else
4475                         cFYI(1, "FindNext returned = %d", rc);
4476         } else {                /* decode response */
4477                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4478
4479                 if (rc == 0) {
4480                         unsigned int lnoff;
4481
4482                         /* BB fixme add lock for file (srch_info) struct here */
4483                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4484                                 psrch_inf->unicode = true;
4485                         else
4486                                 psrch_inf->unicode = false;
4487                         response_data = (char *) &pSMBr->hdr.Protocol +
4488                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4489                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4490                         response_data = (char *)&pSMBr->hdr.Protocol +
4491                                 le16_to_cpu(pSMBr->t2.DataOffset);
4492                         if (psrch_inf->smallBuf)
4493                                 cifs_small_buf_release(
4494                                         psrch_inf->ntwrk_buf_start);
4495                         else
4496                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4497                         psrch_inf->srch_entries_start = response_data;
4498                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4499                         psrch_inf->smallBuf = 0;
4500                         if (parms->EndofSearch)
4501                                 psrch_inf->endOfSearch = true;
4502                         else
4503                                 psrch_inf->endOfSearch = false;
4504                         psrch_inf->entries_in_buffer =
4505                                                 le16_to_cpu(parms->SearchCount);
4506                         psrch_inf->index_of_last_entry +=
4507                                 psrch_inf->entries_in_buffer;
4508                         lnoff = le16_to_cpu(parms->LastNameOffset);
4509                         if (CIFSMaxBufSize < lnoff) {
4510                                 cERROR(1, "ignoring corrupt resume name");
4511                                 psrch_inf->last_entry = NULL;
4512                                 return rc;
4513                         } else
4514                                 psrch_inf->last_entry =
4515                                         psrch_inf->srch_entries_start + lnoff;
4516
4517 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4518             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4519
4520                         /* BB fixme add unlock here */
4521                 }
4522
4523         }
4524
4525         /* BB On error, should we leave previous search buf (and count and
4526         last entry fields) intact or free the previous one? */
4527
4528         /* Note: On -EAGAIN error only caller can retry on handle based calls
4529         since file handle passed in no longer valid */
4530 FNext2_err_exit:
4531         if (rc != 0)
4532                 cifs_buf_release(pSMB);
4533         return rc;
4534 }
4535
4536 int
4537 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4538               const __u16 searchHandle)
4539 {
4540         int rc = 0;
4541         FINDCLOSE_REQ *pSMB = NULL;
4542
4543         cFYI(1, "In CIFSSMBFindClose");
4544         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4545
4546         /* no sense returning error if session restarted
4547                 as file handle has been closed */
4548         if (rc == -EAGAIN)
4549                 return 0;
4550         if (rc)
4551                 return rc;
4552
4553         pSMB->FileID = searchHandle;
4554         pSMB->ByteCount = 0;
4555         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4556         if (rc)
4557                 cERROR(1, "Send error in FindClose = %d", rc);
4558
4559         cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4560
4561         /* Since session is dead, search handle closed on server already */
4562         if (rc == -EAGAIN)
4563                 rc = 0;
4564
4565         return rc;
4566 }
4567
4568 int
4569 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4570                       const char *search_name, __u64 *inode_number,
4571                       const struct nls_table *nls_codepage, int remap)
4572 {
4573         int rc = 0;
4574         TRANSACTION2_QPI_REQ *pSMB = NULL;
4575         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4576         int name_len, bytes_returned;
4577         __u16 params, byte_count;
4578
4579         cFYI(1, "In GetSrvInodeNum for %s", search_name);
4580         if (tcon == NULL)
4581                 return -ENODEV;
4582
4583 GetInodeNumberRetry:
4584         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4585                       (void **) &pSMBr);
4586         if (rc)
4587                 return rc;
4588
4589         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4590                 name_len =
4591                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4592                                            search_name, PATH_MAX, nls_codepage,
4593                                            remap);
4594                 name_len++;     /* trailing null */
4595                 name_len *= 2;
4596         } else {        /* BB improve the check for buffer overruns BB */
4597                 name_len = strnlen(search_name, PATH_MAX);
4598                 name_len++;     /* trailing null */
4599                 strncpy(pSMB->FileName, search_name, name_len);
4600         }
4601
4602         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4603         pSMB->TotalDataCount = 0;
4604         pSMB->MaxParameterCount = cpu_to_le16(2);
4605         /* BB find exact max data count below from sess structure BB */
4606         pSMB->MaxDataCount = cpu_to_le16(4000);
4607         pSMB->MaxSetupCount = 0;
4608         pSMB->Reserved = 0;
4609         pSMB->Flags = 0;
4610         pSMB->Timeout = 0;
4611         pSMB->Reserved2 = 0;
4612         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4613                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4614         pSMB->DataCount = 0;
4615         pSMB->DataOffset = 0;
4616         pSMB->SetupCount = 1;
4617         pSMB->Reserved3 = 0;
4618         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4619         byte_count = params + 1 /* pad */ ;
4620         pSMB->TotalParameterCount = cpu_to_le16(params);
4621         pSMB->ParameterCount = pSMB->TotalParameterCount;
4622         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4623         pSMB->Reserved4 = 0;
4624         inc_rfc1001_len(pSMB, byte_count);
4625         pSMB->ByteCount = cpu_to_le16(byte_count);
4626
4627         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4628                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4629         if (rc) {
4630                 cFYI(1, "error %d in QueryInternalInfo", rc);
4631         } else {
4632                 /* decode response */
4633                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4634                 /* BB also check enough total bytes returned */
4635                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4636                         /* If rc should we check for EOPNOSUPP and
4637                         disable the srvino flag? or in caller? */
4638                         rc = -EIO;      /* bad smb */
4639                 else {
4640                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4641                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4642                         struct file_internal_info *pfinfo;
4643                         /* BB Do we need a cast or hash here ? */
4644                         if (count < 8) {
4645                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4646                                 rc = -EIO;
4647                                 goto GetInodeNumOut;
4648                         }
4649                         pfinfo = (struct file_internal_info *)
4650                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4651                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4652                 }
4653         }
4654 GetInodeNumOut:
4655         cifs_buf_release(pSMB);
4656         if (rc == -EAGAIN)
4657                 goto GetInodeNumberRetry;
4658         return rc;
4659 }
4660
4661 /* parses DFS refferal V3 structure
4662  * caller is responsible for freeing target_nodes
4663  * returns:
4664  *      on success - 0
4665  *      on failure - errno
4666  */
4667 static int
4668 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4669                 unsigned int *num_of_nodes,
4670                 struct dfs_info3_param **target_nodes,
4671                 const struct nls_table *nls_codepage, int remap,
4672                 const char *searchName)
4673 {
4674         int i, rc = 0;
4675         char *data_end;
4676         bool is_unicode;
4677         struct dfs_referral_level_3 *ref;
4678
4679         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4680                 is_unicode = true;
4681         else
4682                 is_unicode = false;
4683         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4684
4685         if (*num_of_nodes < 1) {
4686                 cERROR(1, "num_referrals: must be at least > 0,"
4687                         "but we get num_referrals = %d", *num_of_nodes);
4688                 rc = -EINVAL;
4689                 goto parse_DFS_referrals_exit;
4690         }
4691
4692         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4693         if (ref->VersionNumber != cpu_to_le16(3)) {
4694                 cERROR(1, "Referrals of V%d version are not supported,"
4695                         "should be V3", le16_to_cpu(ref->VersionNumber));
4696                 rc = -EINVAL;
4697                 goto parse_DFS_referrals_exit;
4698         }
4699
4700         /* get the upper boundary of the resp buffer */
4701         data_end = (char *)(&(pSMBr->PathConsumed)) +
4702                                 le16_to_cpu(pSMBr->t2.DataCount);
4703
4704         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4705                         *num_of_nodes,
4706                         le32_to_cpu(pSMBr->DFSFlags));
4707
4708         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4709                         *num_of_nodes, GFP_KERNEL);
4710         if (*target_nodes == NULL) {
4711                 cERROR(1, "Failed to allocate buffer for target_nodes");
4712                 rc = -ENOMEM;
4713                 goto parse_DFS_referrals_exit;
4714         }
4715
4716         /* collect necessary data from referrals */
4717         for (i = 0; i < *num_of_nodes; i++) {
4718                 char *temp;
4719                 int max_len;
4720                 struct dfs_info3_param *node = (*target_nodes)+i;
4721
4722                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4723                 if (is_unicode) {
4724                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4725                                                 GFP_KERNEL);
4726                         if (tmp == NULL) {
4727                                 rc = -ENOMEM;
4728                                 goto parse_DFS_referrals_exit;
4729                         }
4730                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4731                                            PATH_MAX, nls_codepage, remap);
4732                         node->path_consumed = cifs_utf16_bytes(tmp,
4733                                         le16_to_cpu(pSMBr->PathConsumed),
4734                                         nls_codepage);
4735                         kfree(tmp);
4736                 } else
4737                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4738
4739                 node->server_type = le16_to_cpu(ref->ServerType);
4740                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4741
4742                 /* copy DfsPath */
4743                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4744                 max_len = data_end - temp;
4745                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4746                                                 is_unicode, nls_codepage);
4747                 if (!node->path_name) {
4748                         rc = -ENOMEM;
4749                         goto parse_DFS_referrals_exit;
4750                 }
4751
4752                 /* copy link target UNC */
4753                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4754                 max_len = data_end - temp;
4755                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4756                                                 is_unicode, nls_codepage);
4757                 if (!node->node_name) {
4758                         rc = -ENOMEM;
4759                         goto parse_DFS_referrals_exit;
4760                 }
4761
4762                 ref++;
4763         }
4764
4765 parse_DFS_referrals_exit:
4766         if (rc) {
4767                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4768                 *target_nodes = NULL;
4769                 *num_of_nodes = 0;
4770         }
4771         return rc;
4772 }
4773
4774 int
4775 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4776                 const char *search_name, struct dfs_info3_param **target_nodes,
4777                 unsigned int *num_of_nodes,
4778                 const struct nls_table *nls_codepage, int remap)
4779 {
4780 /* TRANS2_GET_DFS_REFERRAL */
4781         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4782         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4783         int rc = 0;
4784         int bytes_returned;
4785         int name_len;
4786         __u16 params, byte_count;
4787         *num_of_nodes = 0;
4788         *target_nodes = NULL;
4789
4790         cFYI(1, "In GetDFSRefer the path %s", search_name);
4791         if (ses == NULL)
4792                 return -ENODEV;
4793 getDFSRetry:
4794         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4795                       (void **) &pSMBr);
4796         if (rc)
4797                 return rc;
4798
4799         /* server pointer checked in called function,
4800         but should never be null here anyway */
4801         pSMB->hdr.Mid = get_next_mid(ses->server);
4802         pSMB->hdr.Tid = ses->ipc_tid;
4803         pSMB->hdr.Uid = ses->Suid;
4804         if (ses->capabilities & CAP_STATUS32)
4805                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4806         if (ses->capabilities & CAP_DFS)
4807                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4808
4809         if (ses->capabilities & CAP_UNICODE) {
4810                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4811                 name_len =
4812                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4813                                        search_name, PATH_MAX, nls_codepage,
4814                                        remap);
4815                 name_len++;     /* trailing null */
4816                 name_len *= 2;
4817         } else {        /* BB improve the check for buffer overruns BB */
4818                 name_len = strnlen(search_name, PATH_MAX);
4819                 name_len++;     /* trailing null */
4820                 strncpy(pSMB->RequestFileName, search_name, name_len);
4821         }
4822
4823         if (ses->server) {
4824                 if (ses->server->sec_mode &
4825                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4826                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4827         }
4828
4829         pSMB->hdr.Uid = ses->Suid;
4830
4831         params = 2 /* level */  + name_len /*includes null */ ;
4832         pSMB->TotalDataCount = 0;
4833         pSMB->DataCount = 0;
4834         pSMB->DataOffset = 0;
4835         pSMB->MaxParameterCount = 0;
4836         /* BB find exact max SMB PDU from sess structure BB */
4837         pSMB->MaxDataCount = cpu_to_le16(4000);
4838         pSMB->MaxSetupCount = 0;
4839         pSMB->Reserved = 0;
4840         pSMB->Flags = 0;
4841         pSMB->Timeout = 0;
4842         pSMB->Reserved2 = 0;
4843         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4844           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4845         pSMB->SetupCount = 1;
4846         pSMB->Reserved3 = 0;
4847         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4848         byte_count = params + 3 /* pad */ ;
4849         pSMB->ParameterCount = cpu_to_le16(params);
4850         pSMB->TotalParameterCount = pSMB->ParameterCount;
4851         pSMB->MaxReferralLevel = cpu_to_le16(3);
4852         inc_rfc1001_len(pSMB, byte_count);
4853         pSMB->ByteCount = cpu_to_le16(byte_count);
4854
4855         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4856                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4857         if (rc) {
4858                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4859                 goto GetDFSRefExit;
4860         }
4861         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4862
4863         /* BB Also check if enough total bytes returned? */
4864         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4865                 rc = -EIO;      /* bad smb */
4866                 goto GetDFSRefExit;
4867         }
4868
4869         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4870                                 get_bcc(&pSMBr->hdr),
4871                                 le16_to_cpu(pSMBr->t2.DataOffset));
4872
4873         /* parse returned result into more usable form */
4874         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4875                                  target_nodes, nls_codepage, remap,
4876                                  search_name);
4877
4878 GetDFSRefExit:
4879         cifs_buf_release(pSMB);
4880
4881         if (rc == -EAGAIN)
4882                 goto getDFSRetry;
4883
4884         return rc;
4885 }
4886
4887 /* Query File System Info such as free space to old servers such as Win 9x */
4888 int
4889 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4890               struct kstatfs *FSData)
4891 {
4892 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4893         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4894         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4895         FILE_SYSTEM_ALLOC_INFO *response_data;
4896         int rc = 0;
4897         int bytes_returned = 0;
4898         __u16 params, byte_count;
4899
4900         cFYI(1, "OldQFSInfo");
4901 oldQFSInfoRetry:
4902         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4903                 (void **) &pSMBr);
4904         if (rc)
4905                 return rc;
4906
4907         params = 2;     /* level */
4908         pSMB->TotalDataCount = 0;
4909         pSMB->MaxParameterCount = cpu_to_le16(2);
4910         pSMB->MaxDataCount = cpu_to_le16(1000);
4911         pSMB->MaxSetupCount = 0;
4912         pSMB->Reserved = 0;
4913         pSMB->Flags = 0;
4914         pSMB->Timeout = 0;
4915         pSMB->Reserved2 = 0;
4916         byte_count = params + 1 /* pad */ ;
4917         pSMB->TotalParameterCount = cpu_to_le16(params);
4918         pSMB->ParameterCount = pSMB->TotalParameterCount;
4919         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4920         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4921         pSMB->DataCount = 0;
4922         pSMB->DataOffset = 0;
4923         pSMB->SetupCount = 1;
4924         pSMB->Reserved3 = 0;
4925         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4926         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4927         inc_rfc1001_len(pSMB, byte_count);
4928         pSMB->ByteCount = cpu_to_le16(byte_count);
4929
4930         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4931                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4932         if (rc) {
4933                 cFYI(1, "Send error in QFSInfo = %d", rc);
4934         } else {                /* decode response */
4935                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4936
4937                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4938                         rc = -EIO;      /* bad smb */
4939                 else {
4940                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4941                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4942                                  get_bcc(&pSMBr->hdr), data_offset);
4943
4944                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4945                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4946                         FSData->f_bsize =
4947                                 le16_to_cpu(response_data->BytesPerSector) *
4948                                 le32_to_cpu(response_data->
4949                                         SectorsPerAllocationUnit);
4950                         FSData->f_blocks =
4951                                le32_to_cpu(response_data->TotalAllocationUnits);
4952                         FSData->f_bfree = FSData->f_bavail =
4953                                 le32_to_cpu(response_data->FreeAllocationUnits);
4954                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4955                              (unsigned long long)FSData->f_blocks,
4956                              (unsigned long long)FSData->f_bfree,
4957                              FSData->f_bsize);
4958                 }
4959         }
4960         cifs_buf_release(pSMB);
4961
4962         if (rc == -EAGAIN)
4963                 goto oldQFSInfoRetry;
4964
4965         return rc;
4966 }
4967
4968 int
4969 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4970                struct kstatfs *FSData)
4971 {
4972 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4973         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4974         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4975         FILE_SYSTEM_INFO *response_data;
4976         int rc = 0;
4977         int bytes_returned = 0;
4978         __u16 params, byte_count;
4979
4980         cFYI(1, "In QFSInfo");
4981 QFSInfoRetry:
4982         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4983                       (void **) &pSMBr);
4984         if (rc)
4985                 return rc;
4986
4987         params = 2;     /* level */
4988         pSMB->TotalDataCount = 0;
4989         pSMB->MaxParameterCount = cpu_to_le16(2);
4990         pSMB->MaxDataCount = cpu_to_le16(1000);
4991         pSMB->MaxSetupCount = 0;
4992         pSMB->Reserved = 0;
4993         pSMB->Flags = 0;
4994         pSMB->Timeout = 0;
4995         pSMB->Reserved2 = 0;
4996         byte_count = params + 1 /* pad */ ;
4997         pSMB->TotalParameterCount = cpu_to_le16(params);
4998         pSMB->ParameterCount = pSMB->TotalParameterCount;
4999         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5000                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5001         pSMB->DataCount = 0;
5002         pSMB->DataOffset = 0;
5003         pSMB->SetupCount = 1;
5004         pSMB->Reserved3 = 0;
5005         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5006         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5007         inc_rfc1001_len(pSMB, byte_count);
5008         pSMB->ByteCount = cpu_to_le16(byte_count);
5009
5010         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5011                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5012         if (rc) {
5013                 cFYI(1, "Send error in QFSInfo = %d", rc);
5014         } else {                /* decode response */
5015                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5016
5017                 if (rc || get_bcc(&pSMBr->hdr) < 24)
5018                         rc = -EIO;      /* bad smb */
5019                 else {
5020                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5021
5022                         response_data =
5023                             (FILE_SYSTEM_INFO
5024                              *) (((char *) &pSMBr->hdr.Protocol) +
5025                                  data_offset);
5026                         FSData->f_bsize =
5027                             le32_to_cpu(response_data->BytesPerSector) *
5028                             le32_to_cpu(response_data->
5029                                         SectorsPerAllocationUnit);
5030                         FSData->f_blocks =
5031                             le64_to_cpu(response_data->TotalAllocationUnits);
5032                         FSData->f_bfree = FSData->f_bavail =
5033                             le64_to_cpu(response_data->FreeAllocationUnits);
5034                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5035                              (unsigned long long)FSData->f_blocks,
5036                              (unsigned long long)FSData->f_bfree,
5037                              FSData->f_bsize);
5038                 }
5039         }
5040         cifs_buf_release(pSMB);
5041
5042         if (rc == -EAGAIN)
5043                 goto QFSInfoRetry;
5044
5045         return rc;
5046 }
5047
5048 int
5049 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5050 {
5051 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5052         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5053         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5054         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5055         int rc = 0;
5056         int bytes_returned = 0;
5057         __u16 params, byte_count;
5058
5059         cFYI(1, "In QFSAttributeInfo");
5060 QFSAttributeRetry:
5061         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5062                       (void **) &pSMBr);
5063         if (rc)
5064                 return rc;
5065
5066         params = 2;     /* level */
5067         pSMB->TotalDataCount = 0;
5068         pSMB->MaxParameterCount = cpu_to_le16(2);
5069         /* BB find exact max SMB PDU from sess structure BB */
5070         pSMB->MaxDataCount = cpu_to_le16(1000);
5071         pSMB->MaxSetupCount = 0;
5072         pSMB->Reserved = 0;
5073         pSMB->Flags = 0;
5074         pSMB->Timeout = 0;
5075         pSMB->Reserved2 = 0;
5076         byte_count = params + 1 /* pad */ ;
5077         pSMB->TotalParameterCount = cpu_to_le16(params);
5078         pSMB->ParameterCount = pSMB->TotalParameterCount;
5079         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5080                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5081         pSMB->DataCount = 0;
5082         pSMB->DataOffset = 0;
5083         pSMB->SetupCount = 1;
5084         pSMB->Reserved3 = 0;
5085         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5086         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5087         inc_rfc1001_len(pSMB, byte_count);
5088         pSMB->ByteCount = cpu_to_le16(byte_count);
5089
5090         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5091                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5092         if (rc) {
5093                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5094         } else {                /* decode response */
5095                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5096
5097                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5098                         /* BB also check if enough bytes returned */
5099                         rc = -EIO;      /* bad smb */
5100                 } else {
5101                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5102                         response_data =
5103                             (FILE_SYSTEM_ATTRIBUTE_INFO
5104                              *) (((char *) &pSMBr->hdr.Protocol) +
5105                                  data_offset);
5106                         memcpy(&tcon->fsAttrInfo, response_data,
5107                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5108                 }
5109         }
5110         cifs_buf_release(pSMB);
5111
5112         if (rc == -EAGAIN)
5113                 goto QFSAttributeRetry;
5114
5115         return rc;
5116 }
5117
5118 int
5119 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5120 {
5121 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5122         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5123         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5124         FILE_SYSTEM_DEVICE_INFO *response_data;
5125         int rc = 0;
5126         int bytes_returned = 0;
5127         __u16 params, byte_count;
5128
5129         cFYI(1, "In QFSDeviceInfo");
5130 QFSDeviceRetry:
5131         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5132                       (void **) &pSMBr);
5133         if (rc)
5134                 return rc;
5135
5136         params = 2;     /* level */
5137         pSMB->TotalDataCount = 0;
5138         pSMB->MaxParameterCount = cpu_to_le16(2);
5139         /* BB find exact max SMB PDU from sess structure BB */
5140         pSMB->MaxDataCount = cpu_to_le16(1000);
5141         pSMB->MaxSetupCount = 0;
5142         pSMB->Reserved = 0;
5143         pSMB->Flags = 0;
5144         pSMB->Timeout = 0;
5145         pSMB->Reserved2 = 0;
5146         byte_count = params + 1 /* pad */ ;
5147         pSMB->TotalParameterCount = cpu_to_le16(params);
5148         pSMB->ParameterCount = pSMB->TotalParameterCount;
5149         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5150                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5151
5152         pSMB->DataCount = 0;
5153         pSMB->DataOffset = 0;
5154         pSMB->SetupCount = 1;
5155         pSMB->Reserved3 = 0;
5156         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5157         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5158         inc_rfc1001_len(pSMB, byte_count);
5159         pSMB->ByteCount = cpu_to_le16(byte_count);
5160
5161         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5162                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5163         if (rc) {
5164                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5165         } else {                /* decode response */
5166                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5167
5168                 if (rc || get_bcc(&pSMBr->hdr) <
5169                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5170                         rc = -EIO;      /* bad smb */
5171                 else {
5172                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5173                         response_data =
5174                             (FILE_SYSTEM_DEVICE_INFO *)
5175                                 (((char *) &pSMBr->hdr.Protocol) +
5176                                  data_offset);
5177                         memcpy(&tcon->fsDevInfo, response_data,
5178                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5179                 }
5180         }
5181         cifs_buf_release(pSMB);
5182
5183         if (rc == -EAGAIN)
5184                 goto QFSDeviceRetry;
5185
5186         return rc;
5187 }
5188
5189 int
5190 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5191 {
5192 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5193         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5194         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5195         FILE_SYSTEM_UNIX_INFO *response_data;
5196         int rc = 0;
5197         int bytes_returned = 0;
5198         __u16 params, byte_count;
5199
5200         cFYI(1, "In QFSUnixInfo");
5201 QFSUnixRetry:
5202         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5203                                    (void **) &pSMB, (void **) &pSMBr);
5204         if (rc)
5205                 return rc;
5206
5207         params = 2;     /* level */
5208         pSMB->TotalDataCount = 0;
5209         pSMB->DataCount = 0;
5210         pSMB->DataOffset = 0;
5211         pSMB->MaxParameterCount = cpu_to_le16(2);
5212         /* BB find exact max SMB PDU from sess structure BB */
5213         pSMB->MaxDataCount = cpu_to_le16(100);
5214         pSMB->MaxSetupCount = 0;
5215         pSMB->Reserved = 0;
5216         pSMB->Flags = 0;
5217         pSMB->Timeout = 0;
5218         pSMB->Reserved2 = 0;
5219         byte_count = params + 1 /* pad */ ;
5220         pSMB->ParameterCount = cpu_to_le16(params);
5221         pSMB->TotalParameterCount = pSMB->ParameterCount;
5222         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5223                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5224         pSMB->SetupCount = 1;
5225         pSMB->Reserved3 = 0;
5226         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5227         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5228         inc_rfc1001_len(pSMB, byte_count);
5229         pSMB->ByteCount = cpu_to_le16(byte_count);
5230
5231         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5232                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5233         if (rc) {
5234                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5235         } else {                /* decode response */
5236                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5237
5238                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5239                         rc = -EIO;      /* bad smb */
5240                 } else {
5241                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5242                         response_data =
5243                             (FILE_SYSTEM_UNIX_INFO
5244                              *) (((char *) &pSMBr->hdr.Protocol) +
5245                                  data_offset);
5246                         memcpy(&tcon->fsUnixInfo, response_data,
5247                                sizeof(FILE_SYSTEM_UNIX_INFO));
5248                 }
5249         }
5250         cifs_buf_release(pSMB);
5251
5252         if (rc == -EAGAIN)
5253                 goto QFSUnixRetry;
5254
5255
5256         return rc;
5257 }
5258
5259 int
5260 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5261 {
5262 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5263         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5264         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5265         int rc = 0;
5266         int bytes_returned = 0;
5267         __u16 params, param_offset, offset, byte_count;
5268
5269         cFYI(1, "In SETFSUnixInfo");
5270 SETFSUnixRetry:
5271         /* BB switch to small buf init to save memory */
5272         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5273                                         (void **) &pSMB, (void **) &pSMBr);
5274         if (rc)
5275                 return rc;
5276
5277         params = 4;     /* 2 bytes zero followed by info level. */
5278         pSMB->MaxSetupCount = 0;
5279         pSMB->Reserved = 0;
5280         pSMB->Flags = 0;
5281         pSMB->Timeout = 0;
5282         pSMB->Reserved2 = 0;
5283         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5284                                 - 4;
5285         offset = param_offset + params;
5286
5287         pSMB->MaxParameterCount = cpu_to_le16(4);
5288         /* BB find exact max SMB PDU from sess structure BB */
5289         pSMB->MaxDataCount = cpu_to_le16(100);
5290         pSMB->SetupCount = 1;
5291         pSMB->Reserved3 = 0;
5292         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5293         byte_count = 1 /* pad */ + params + 12;
5294
5295         pSMB->DataCount = cpu_to_le16(12);
5296         pSMB->ParameterCount = cpu_to_le16(params);
5297         pSMB->TotalDataCount = pSMB->DataCount;
5298         pSMB->TotalParameterCount = pSMB->ParameterCount;
5299         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5300         pSMB->DataOffset = cpu_to_le16(offset);
5301
5302         /* Params. */
5303         pSMB->FileNum = 0;
5304         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5305
5306         /* Data. */
5307         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5308         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5309         pSMB->ClientUnixCap = cpu_to_le64(cap);
5310
5311         inc_rfc1001_len(pSMB, byte_count);
5312         pSMB->ByteCount = cpu_to_le16(byte_count);
5313
5314         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5315                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5316         if (rc) {
5317                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5318         } else {                /* decode response */
5319                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5320                 if (rc)
5321                         rc = -EIO;      /* bad smb */
5322         }
5323         cifs_buf_release(pSMB);
5324
5325         if (rc == -EAGAIN)
5326                 goto SETFSUnixRetry;
5327
5328         return rc;
5329 }
5330
5331
5332
5333 int
5334 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5335                    struct kstatfs *FSData)
5336 {
5337 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5338         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5339         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5340         FILE_SYSTEM_POSIX_INFO *response_data;
5341         int rc = 0;
5342         int bytes_returned = 0;
5343         __u16 params, byte_count;
5344
5345         cFYI(1, "In QFSPosixInfo");
5346 QFSPosixRetry:
5347         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5348                       (void **) &pSMBr);
5349         if (rc)
5350                 return rc;
5351
5352         params = 2;     /* level */
5353         pSMB->TotalDataCount = 0;
5354         pSMB->DataCount = 0;
5355         pSMB->DataOffset = 0;
5356         pSMB->MaxParameterCount = cpu_to_le16(2);
5357         /* BB find exact max SMB PDU from sess structure BB */
5358         pSMB->MaxDataCount = cpu_to_le16(100);
5359         pSMB->MaxSetupCount = 0;
5360         pSMB->Reserved = 0;
5361         pSMB->Flags = 0;
5362         pSMB->Timeout = 0;
5363         pSMB->Reserved2 = 0;
5364         byte_count = params + 1 /* pad */ ;
5365         pSMB->ParameterCount = cpu_to_le16(params);
5366         pSMB->TotalParameterCount = pSMB->ParameterCount;
5367         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5368                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5369         pSMB->SetupCount = 1;
5370         pSMB->Reserved3 = 0;
5371         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5372         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5373         inc_rfc1001_len(pSMB, byte_count);
5374         pSMB->ByteCount = cpu_to_le16(byte_count);
5375
5376         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5377                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5378         if (rc) {
5379                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5380         } else {                /* decode response */
5381                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5382
5383                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5384                         rc = -EIO;      /* bad smb */
5385                 } else {
5386                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5387                         response_data =
5388                             (FILE_SYSTEM_POSIX_INFO
5389                              *) (((char *) &pSMBr->hdr.Protocol) +
5390                                  data_offset);
5391                         FSData->f_bsize =
5392                                         le32_to_cpu(response_data->BlockSize);
5393                         FSData->f_blocks =
5394                                         le64_to_cpu(response_data->TotalBlocks);
5395                         FSData->f_bfree =
5396                             le64_to_cpu(response_data->BlocksAvail);
5397                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5398                                 FSData->f_bavail = FSData->f_bfree;
5399                         } else {
5400                                 FSData->f_bavail =
5401                                     le64_to_cpu(response_data->UserBlocksAvail);
5402                         }
5403                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5404                                 FSData->f_files =
5405                                      le64_to_cpu(response_data->TotalFileNodes);
5406                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5407                                 FSData->f_ffree =
5408                                       le64_to_cpu(response_data->FreeFileNodes);
5409                 }
5410         }
5411         cifs_buf_release(pSMB);
5412
5413         if (rc == -EAGAIN)
5414                 goto QFSPosixRetry;
5415
5416         return rc;
5417 }
5418
5419
5420 /* We can not use write of zero bytes trick to
5421    set file size due to need for large file support.  Also note that
5422    this SetPathInfo is preferred to SetFileInfo based method in next
5423    routine which is only needed to work around a sharing violation bug
5424    in Samba which this routine can run into */
5425
5426 int
5427 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5428               const char *fileName, __u64 size, bool SetAllocation,
5429               const struct nls_table *nls_codepage, int remap)
5430 {
5431         struct smb_com_transaction2_spi_req *pSMB = NULL;
5432         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5433         struct file_end_of_file_info *parm_data;
5434         int name_len;
5435         int rc = 0;
5436         int bytes_returned = 0;
5437         __u16 params, byte_count, data_count, param_offset, offset;
5438
5439         cFYI(1, "In SetEOF");
5440 SetEOFRetry:
5441         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5442                       (void **) &pSMBr);
5443         if (rc)
5444                 return rc;
5445
5446         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5447                 name_len =
5448                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5449                                        PATH_MAX, nls_codepage, remap);
5450                 name_len++;     /* trailing null */
5451                 name_len *= 2;
5452         } else {        /* BB improve the check for buffer overruns BB */
5453                 name_len = strnlen(fileName, PATH_MAX);
5454                 name_len++;     /* trailing null */
5455                 strncpy(pSMB->FileName, fileName, name_len);
5456         }
5457         params = 6 + name_len;
5458         data_count = sizeof(struct file_end_of_file_info);
5459         pSMB->MaxParameterCount = cpu_to_le16(2);
5460         pSMB->MaxDataCount = cpu_to_le16(4100);
5461         pSMB->MaxSetupCount = 0;
5462         pSMB->Reserved = 0;
5463         pSMB->Flags = 0;
5464         pSMB->Timeout = 0;
5465         pSMB->Reserved2 = 0;
5466         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5467                                 InformationLevel) - 4;
5468         offset = param_offset + params;
5469         if (SetAllocation) {
5470                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5471                         pSMB->InformationLevel =
5472                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5473                 else
5474                         pSMB->InformationLevel =
5475                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5476         } else /* Set File Size */  {
5477             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5478                     pSMB->InformationLevel =
5479                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5480             else
5481                     pSMB->InformationLevel =
5482                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5483         }
5484
5485         parm_data =
5486             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5487                                        offset);
5488         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5489         pSMB->DataOffset = cpu_to_le16(offset);
5490         pSMB->SetupCount = 1;
5491         pSMB->Reserved3 = 0;
5492         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5493         byte_count = 3 /* pad */  + params + data_count;
5494         pSMB->DataCount = cpu_to_le16(data_count);
5495         pSMB->TotalDataCount = pSMB->DataCount;
5496         pSMB->ParameterCount = cpu_to_le16(params);
5497         pSMB->TotalParameterCount = pSMB->ParameterCount;
5498         pSMB->Reserved4 = 0;
5499         inc_rfc1001_len(pSMB, byte_count);
5500         parm_data->FileSize = cpu_to_le64(size);
5501         pSMB->ByteCount = cpu_to_le16(byte_count);
5502         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5503                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5504         if (rc)
5505                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5506
5507         cifs_buf_release(pSMB);
5508
5509         if (rc == -EAGAIN)
5510                 goto SetEOFRetry;
5511
5512         return rc;
5513 }
5514
5515 int
5516 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5517                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5518 {
5519         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5520         struct file_end_of_file_info *parm_data;
5521         int rc = 0;
5522         __u16 params, param_offset, offset, byte_count, count;
5523
5524         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5525                         (long long)size);
5526         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5527
5528         if (rc)
5529                 return rc;
5530
5531         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5532         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5533
5534         params = 6;
5535         pSMB->MaxSetupCount = 0;
5536         pSMB->Reserved = 0;
5537         pSMB->Flags = 0;
5538         pSMB->Timeout = 0;
5539         pSMB->Reserved2 = 0;
5540         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5541         offset = param_offset + params;
5542
5543         count = sizeof(struct file_end_of_file_info);
5544         pSMB->MaxParameterCount = cpu_to_le16(2);
5545         /* BB find exact max SMB PDU from sess structure BB */
5546         pSMB->MaxDataCount = cpu_to_le16(1000);
5547         pSMB->SetupCount = 1;
5548         pSMB->Reserved3 = 0;
5549         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5550         byte_count = 3 /* pad */  + params + count;
5551         pSMB->DataCount = cpu_to_le16(count);
5552         pSMB->ParameterCount = cpu_to_le16(params);
5553         pSMB->TotalDataCount = pSMB->DataCount;
5554         pSMB->TotalParameterCount = pSMB->ParameterCount;
5555         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5556         parm_data =
5557                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5558                                 + offset);
5559         pSMB->DataOffset = cpu_to_le16(offset);
5560         parm_data->FileSize = cpu_to_le64(size);
5561         pSMB->Fid = fid;
5562         if (SetAllocation) {
5563                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5564                         pSMB->InformationLevel =
5565                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5566                 else
5567                         pSMB->InformationLevel =
5568                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5569         } else /* Set File Size */  {
5570             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5571                     pSMB->InformationLevel =
5572                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5573             else
5574                     pSMB->InformationLevel =
5575                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5576         }
5577         pSMB->Reserved4 = 0;
5578         inc_rfc1001_len(pSMB, byte_count);
5579         pSMB->ByteCount = cpu_to_le16(byte_count);
5580         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5581         if (rc) {
5582                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5583         }
5584
5585         /* Note: On -EAGAIN error only caller can retry on handle based calls
5586                 since file handle passed in no longer valid */
5587
5588         return rc;
5589 }
5590
5591 /* Some legacy servers such as NT4 require that the file times be set on
5592    an open handle, rather than by pathname - this is awkward due to
5593    potential access conflicts on the open, but it is unavoidable for these
5594    old servers since the only other choice is to go from 100 nanosecond DCE
5595    time and resort to the original setpathinfo level which takes the ancient
5596    DOS time format with 2 second granularity */
5597 int
5598 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5599                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5600 {
5601         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5602         char *data_offset;
5603         int rc = 0;
5604         __u16 params, param_offset, offset, byte_count, count;
5605
5606         cFYI(1, "Set Times (via SetFileInfo)");
5607         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5608
5609         if (rc)
5610                 return rc;
5611
5612         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5613         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5614
5615         params = 6;
5616         pSMB->MaxSetupCount = 0;
5617         pSMB->Reserved = 0;
5618         pSMB->Flags = 0;
5619         pSMB->Timeout = 0;
5620         pSMB->Reserved2 = 0;
5621         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5622         offset = param_offset + params;
5623
5624         data_offset = (char *)pSMB +
5625                         offsetof(struct smb_hdr, Protocol) + offset;
5626
5627         count = sizeof(FILE_BASIC_INFO);
5628         pSMB->MaxParameterCount = cpu_to_le16(2);
5629         /* BB find max SMB PDU from sess */
5630         pSMB->MaxDataCount = cpu_to_le16(1000);
5631         pSMB->SetupCount = 1;
5632         pSMB->Reserved3 = 0;
5633         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5634         byte_count = 3 /* pad */  + params + count;
5635         pSMB->DataCount = cpu_to_le16(count);
5636         pSMB->ParameterCount = cpu_to_le16(params);
5637         pSMB->TotalDataCount = pSMB->DataCount;
5638         pSMB->TotalParameterCount = pSMB->ParameterCount;
5639         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5640         pSMB->DataOffset = cpu_to_le16(offset);
5641         pSMB->Fid = fid;
5642         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5643                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5644         else
5645                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5646         pSMB->Reserved4 = 0;
5647         inc_rfc1001_len(pSMB, byte_count);
5648         pSMB->ByteCount = cpu_to_le16(byte_count);
5649         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5650         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5651         if (rc)
5652                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5653
5654         /* Note: On -EAGAIN error only caller can retry on handle based calls
5655                 since file handle passed in no longer valid */
5656
5657         return rc;
5658 }
5659
5660 int
5661 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5662                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5663 {
5664         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5665         char *data_offset;
5666         int rc = 0;
5667         __u16 params, param_offset, offset, byte_count, count;
5668
5669         cFYI(1, "Set File Disposition (via SetFileInfo)");
5670         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5671
5672         if (rc)
5673                 return rc;
5674
5675         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5676         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5677
5678         params = 6;
5679         pSMB->MaxSetupCount = 0;
5680         pSMB->Reserved = 0;
5681         pSMB->Flags = 0;
5682       &nb