CIFS: Move rmdir code to ops struct
[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                         if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1580                                           server, mid->sequence_number + 1))
1581                                 cERROR(1, "Unexpected SMB signature");
1582                 }
1583                 /* FIXME: should this be counted toward the initiating task? */
1584                 task_io_account_read(rdata->bytes);
1585                 cifs_stats_bytes_read(tcon, rdata->bytes);
1586                 break;
1587         case MID_REQUEST_SUBMITTED:
1588         case MID_RETRY_NEEDED:
1589                 rdata->result = -EAGAIN;
1590                 break;
1591         default:
1592                 rdata->result = -EIO;
1593         }
1594
1595         queue_work(cifsiod_wq, &rdata->work);
1596         DeleteMidQEntry(mid);
1597         add_credits(server, 1, 0);
1598 }
1599
1600 /* cifs_async_readv - send an async write, and set up mid to handle result */
1601 int
1602 cifs_async_readv(struct cifs_readdata *rdata)
1603 {
1604         int rc;
1605         READ_REQ *smb = NULL;
1606         int wct;
1607         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1608
1609         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1610                 rdata->offset, rdata->bytes);
1611
1612         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1613                 wct = 12;
1614         else {
1615                 wct = 10; /* old style read */
1616                 if ((rdata->offset >> 32) > 0)  {
1617                         /* can not handle this big offset for old */
1618                         return -EIO;
1619                 }
1620         }
1621
1622         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1623         if (rc)
1624                 return rc;
1625
1626         smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1627         smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1628
1629         smb->AndXCommand = 0xFF;        /* none */
1630         smb->Fid = rdata->cfile->netfid;
1631         smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1632         if (wct == 12)
1633                 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1634         smb->Remaining = 0;
1635         smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1636         smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1637         if (wct == 12)
1638                 smb->ByteCount = 0;
1639         else {
1640                 /* old style read */
1641                 struct smb_com_readx_req *smbr =
1642                         (struct smb_com_readx_req *)smb;
1643                 smbr->ByteCount = 0;
1644         }
1645
1646         /* 4 for RFC1001 length + 1 for BCC */
1647         rdata->iov[0].iov_base = smb;
1648         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1649
1650         kref_get(&rdata->refcount);
1651         rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1652                              cifs_readv_receive, cifs_readv_callback,
1653                              rdata, 0);
1654
1655         if (rc == 0)
1656                 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1657         else
1658                 kref_put(&rdata->refcount, cifs_readdata_release);
1659
1660         cifs_small_buf_release(smb);
1661         return rc;
1662 }
1663
1664 int
1665 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1666             unsigned int *nbytes, char **buf, int *pbuf_type)
1667 {
1668         int rc = -EACCES;
1669         READ_REQ *pSMB = NULL;
1670         READ_RSP *pSMBr = NULL;
1671         char *pReadData = NULL;
1672         int wct;
1673         int resp_buf_type = 0;
1674         struct kvec iov[1];
1675         __u32 pid = io_parms->pid;
1676         __u16 netfid = io_parms->netfid;
1677         __u64 offset = io_parms->offset;
1678         struct cifs_tcon *tcon = io_parms->tcon;
1679         unsigned int count = io_parms->length;
1680
1681         cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1682         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1683                 wct = 12;
1684         else {
1685                 wct = 10; /* old style read */
1686                 if ((offset >> 32) > 0)  {
1687                         /* can not handle this big offset for old */
1688                         return -EIO;
1689                 }
1690         }
1691
1692         *nbytes = 0;
1693         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1694         if (rc)
1695                 return rc;
1696
1697         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1698         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1699
1700         /* tcon and ses pointer are checked in smb_init */
1701         if (tcon->ses->server == NULL)
1702                 return -ECONNABORTED;
1703
1704         pSMB->AndXCommand = 0xFF;       /* none */
1705         pSMB->Fid = netfid;
1706         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1707         if (wct == 12)
1708                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1709
1710         pSMB->Remaining = 0;
1711         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1712         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1713         if (wct == 12)
1714                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1715         else {
1716                 /* old style read */
1717                 struct smb_com_readx_req *pSMBW =
1718                         (struct smb_com_readx_req *)pSMB;
1719                 pSMBW->ByteCount = 0;
1720         }
1721
1722         iov[0].iov_base = (char *)pSMB;
1723         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1724         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1725                          &resp_buf_type, CIFS_LOG_ERROR);
1726         cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1727         pSMBr = (READ_RSP *)iov[0].iov_base;
1728         if (rc) {
1729                 cERROR(1, "Send error in read = %d", rc);
1730         } else {
1731                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1732                 data_length = data_length << 16;
1733                 data_length += le16_to_cpu(pSMBr->DataLength);
1734                 *nbytes = data_length;
1735
1736                 /*check that DataLength would not go beyond end of SMB */
1737                 if ((data_length > CIFSMaxBufSize)
1738                                 || (data_length > count)) {
1739                         cFYI(1, "bad length %d for count %d",
1740                                  data_length, count);
1741                         rc = -EIO;
1742                         *nbytes = 0;
1743                 } else {
1744                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1745                                         le16_to_cpu(pSMBr->DataOffset);
1746 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1747                                 cERROR(1, "Faulting on read rc = %d",rc);
1748                                 rc = -EFAULT;
1749                         }*/ /* can not use copy_to_user when using page cache*/
1750                         if (*buf)
1751                                 memcpy(*buf, pReadData, data_length);
1752                 }
1753         }
1754
1755 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1756         if (*buf) {
1757                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1758                         cifs_small_buf_release(iov[0].iov_base);
1759                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1760                         cifs_buf_release(iov[0].iov_base);
1761         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1762                 /* return buffer to caller to free */
1763                 *buf = iov[0].iov_base;
1764                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1765                         *pbuf_type = CIFS_SMALL_BUFFER;
1766                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1767                         *pbuf_type = CIFS_LARGE_BUFFER;
1768         } /* else no valid buffer on return - leave as null */
1769
1770         /* Note: On -EAGAIN error only caller can retry on handle based calls
1771                 since file handle passed in no longer valid */
1772         return rc;
1773 }
1774
1775
1776 int
1777 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1778              unsigned int *nbytes, const char *buf,
1779              const char __user *ubuf, const int long_op)
1780 {
1781         int rc = -EACCES;
1782         WRITE_REQ *pSMB = NULL;
1783         WRITE_RSP *pSMBr = NULL;
1784         int bytes_returned, wct;
1785         __u32 bytes_sent;
1786         __u16 byte_count;
1787         __u32 pid = io_parms->pid;
1788         __u16 netfid = io_parms->netfid;
1789         __u64 offset = io_parms->offset;
1790         struct cifs_tcon *tcon = io_parms->tcon;
1791         unsigned int count = io_parms->length;
1792
1793         *nbytes = 0;
1794
1795         /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1796         if (tcon->ses == NULL)
1797                 return -ECONNABORTED;
1798
1799         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1800                 wct = 14;
1801         else {
1802                 wct = 12;
1803                 if ((offset >> 32) > 0) {
1804                         /* can not handle big offset for old srv */
1805                         return -EIO;
1806                 }
1807         }
1808
1809         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1810                       (void **) &pSMBr);
1811         if (rc)
1812                 return rc;
1813
1814         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1815         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1816
1817         /* tcon and ses pointer are checked in smb_init */
1818         if (tcon->ses->server == NULL)
1819                 return -ECONNABORTED;
1820
1821         pSMB->AndXCommand = 0xFF;       /* none */
1822         pSMB->Fid = netfid;
1823         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1824         if (wct == 14)
1825                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1826
1827         pSMB->Reserved = 0xFFFFFFFF;
1828         pSMB->WriteMode = 0;
1829         pSMB->Remaining = 0;
1830
1831         /* Can increase buffer size if buffer is big enough in some cases ie we
1832         can send more if LARGE_WRITE_X capability returned by the server and if
1833         our buffer is big enough or if we convert to iovecs on socket writes
1834         and eliminate the copy to the CIFS buffer */
1835         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1836                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1837         } else {
1838                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1839                          & ~0xFF;
1840         }
1841
1842         if (bytes_sent > count)
1843                 bytes_sent = count;
1844         pSMB->DataOffset =
1845                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1846         if (buf)
1847                 memcpy(pSMB->Data, buf, bytes_sent);
1848         else if (ubuf) {
1849                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1850                         cifs_buf_release(pSMB);
1851                         return -EFAULT;
1852                 }
1853         } else if (count != 0) {
1854                 /* No buffer */
1855                 cifs_buf_release(pSMB);
1856                 return -EINVAL;
1857         } /* else setting file size with write of zero bytes */
1858         if (wct == 14)
1859                 byte_count = bytes_sent + 1; /* pad */
1860         else /* wct == 12 */
1861                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1862
1863         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1864         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1865         inc_rfc1001_len(pSMB, byte_count);
1866
1867         if (wct == 14)
1868                 pSMB->ByteCount = cpu_to_le16(byte_count);
1869         else { /* old style write has byte count 4 bytes earlier
1870                   so 4 bytes pad  */
1871                 struct smb_com_writex_req *pSMBW =
1872                         (struct smb_com_writex_req *)pSMB;
1873                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1874         }
1875
1876         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1877                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1878         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1879         if (rc) {
1880                 cFYI(1, "Send error in write = %d", rc);
1881         } else {
1882                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1883                 *nbytes = (*nbytes) << 16;
1884                 *nbytes += le16_to_cpu(pSMBr->Count);
1885
1886                 /*
1887                  * Mask off high 16 bits when bytes written as returned by the
1888                  * server is greater than bytes requested by the client. Some
1889                  * OS/2 servers are known to set incorrect CountHigh values.
1890                  */
1891                 if (*nbytes > count)
1892                         *nbytes &= 0xFFFF;
1893         }
1894
1895         cifs_buf_release(pSMB);
1896
1897         /* Note: On -EAGAIN error only caller can retry on handle based calls
1898                 since file handle passed in no longer valid */
1899
1900         return rc;
1901 }
1902
1903 void
1904 cifs_writedata_release(struct kref *refcount)
1905 {
1906         struct cifs_writedata *wdata = container_of(refcount,
1907                                         struct cifs_writedata, refcount);
1908
1909         if (wdata->cfile)
1910                 cifsFileInfo_put(wdata->cfile);
1911
1912         kfree(wdata);
1913 }
1914
1915 /*
1916  * Write failed with a retryable error. Resend the write request. It's also
1917  * possible that the page was redirtied so re-clean the page.
1918  */
1919 static void
1920 cifs_writev_requeue(struct cifs_writedata *wdata)
1921 {
1922         int i, rc;
1923         struct inode *inode = wdata->cfile->dentry->d_inode;
1924
1925         for (i = 0; i < wdata->nr_pages; i++) {
1926                 lock_page(wdata->pages[i]);
1927                 clear_page_dirty_for_io(wdata->pages[i]);
1928         }
1929
1930         do {
1931                 rc = cifs_async_writev(wdata);
1932         } while (rc == -EAGAIN);
1933
1934         for (i = 0; i < wdata->nr_pages; i++) {
1935                 if (rc != 0)
1936                         SetPageError(wdata->pages[i]);
1937                 unlock_page(wdata->pages[i]);
1938         }
1939
1940         mapping_set_error(inode->i_mapping, rc);
1941         kref_put(&wdata->refcount, cifs_writedata_release);
1942 }
1943
1944 void
1945 cifs_writev_complete(struct work_struct *work)
1946 {
1947         struct cifs_writedata *wdata = container_of(work,
1948                                                 struct cifs_writedata, work);
1949         struct inode *inode = wdata->cfile->dentry->d_inode;
1950         int i = 0;
1951
1952         if (wdata->result == 0) {
1953                 spin_lock(&inode->i_lock);
1954                 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1955                 spin_unlock(&inode->i_lock);
1956                 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1957                                          wdata->bytes);
1958         } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1959                 return cifs_writev_requeue(wdata);
1960
1961         for (i = 0; i < wdata->nr_pages; i++) {
1962                 struct page *page = wdata->pages[i];
1963                 if (wdata->result == -EAGAIN)
1964                         __set_page_dirty_nobuffers(page);
1965                 else if (wdata->result < 0)
1966                         SetPageError(page);
1967                 end_page_writeback(page);
1968                 page_cache_release(page);
1969         }
1970         if (wdata->result != -EAGAIN)
1971                 mapping_set_error(inode->i_mapping, wdata->result);
1972         kref_put(&wdata->refcount, cifs_writedata_release);
1973 }
1974
1975 struct cifs_writedata *
1976 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1977 {
1978         struct cifs_writedata *wdata;
1979
1980         /* this would overflow */
1981         if (nr_pages == 0) {
1982                 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1983                 return NULL;
1984         }
1985
1986         /* writedata + number of page pointers */
1987         wdata = kzalloc(sizeof(*wdata) +
1988                         sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1989         if (wdata != NULL) {
1990                 kref_init(&wdata->refcount);
1991                 INIT_LIST_HEAD(&wdata->list);
1992                 init_completion(&wdata->done);
1993                 INIT_WORK(&wdata->work, complete);
1994         }
1995         return wdata;
1996 }
1997
1998 /*
1999  * Check the mid_state and signature on received buffer (if any), and queue the
2000  * workqueue completion task.
2001  */
2002 static void
2003 cifs_writev_callback(struct mid_q_entry *mid)
2004 {
2005         struct cifs_writedata *wdata = mid->callback_data;
2006         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2007         unsigned int written;
2008         WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2009
2010         switch (mid->mid_state) {
2011         case MID_RESPONSE_RECEIVED:
2012                 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2013                 if (wdata->result != 0)
2014                         break;
2015
2016                 written = le16_to_cpu(smb->CountHigh);
2017                 written <<= 16;
2018                 written += le16_to_cpu(smb->Count);
2019                 /*
2020                  * Mask off high 16 bits when bytes written as returned
2021                  * by the server is greater than bytes requested by the
2022                  * client. OS/2 servers are known to set incorrect
2023                  * CountHigh values.
2024                  */
2025                 if (written > wdata->bytes)
2026                         written &= 0xFFFF;
2027
2028                 if (written < wdata->bytes)
2029                         wdata->result = -ENOSPC;
2030                 else
2031                         wdata->bytes = written;
2032                 break;
2033         case MID_REQUEST_SUBMITTED:
2034         case MID_RETRY_NEEDED:
2035                 wdata->result = -EAGAIN;
2036                 break;
2037         default:
2038                 wdata->result = -EIO;
2039                 break;
2040         }
2041
2042         queue_work(cifsiod_wq, &wdata->work);
2043         DeleteMidQEntry(mid);
2044         add_credits(tcon->ses->server, 1, 0);
2045 }
2046
2047 /* cifs_async_writev - send an async write, and set up mid to handle result */
2048 int
2049 cifs_async_writev(struct cifs_writedata *wdata)
2050 {
2051         int i, rc = -EACCES;
2052         WRITE_REQ *smb = NULL;
2053         int wct;
2054         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2055         struct kvec *iov = NULL;
2056
2057         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2058                 wct = 14;
2059         } else {
2060                 wct = 12;
2061                 if (wdata->offset >> 32 > 0) {
2062                         /* can not handle big offset for old srv */
2063                         return -EIO;
2064                 }
2065         }
2066
2067         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2068         if (rc)
2069                 goto async_writev_out;
2070
2071         /* 1 iov per page + 1 for header */
2072         iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2073         if (iov == NULL) {
2074                 rc = -ENOMEM;
2075                 goto async_writev_out;
2076         }
2077
2078         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2079         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2080
2081         smb->AndXCommand = 0xFF;        /* none */
2082         smb->Fid = wdata->cfile->netfid;
2083         smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2084         if (wct == 14)
2085                 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2086         smb->Reserved = 0xFFFFFFFF;
2087         smb->WriteMode = 0;
2088         smb->Remaining = 0;
2089
2090         smb->DataOffset =
2091             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2092
2093         /* 4 for RFC1001 length + 1 for BCC */
2094         iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2095         iov[0].iov_base = smb;
2096
2097         /*
2098          * This function should marshal up the page array into the kvec
2099          * array, reserving [0] for the header. It should kmap the pages
2100          * and set the iov_len properly for each one. It may also set
2101          * wdata->bytes too.
2102          */
2103         cifs_kmap_lock();
2104         wdata->marshal_iov(iov, wdata);
2105         cifs_kmap_unlock();
2106
2107         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2108
2109         smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2110         smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2111
2112         if (wct == 14) {
2113                 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2114                 put_bcc(wdata->bytes + 1, &smb->hdr);
2115         } else {
2116                 /* wct == 12 */
2117                 struct smb_com_writex_req *smbw =
2118                                 (struct smb_com_writex_req *)smb;
2119                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2120                 put_bcc(wdata->bytes + 5, &smbw->hdr);
2121                 iov[0].iov_len += 4; /* pad bigger by four bytes */
2122         }
2123
2124         kref_get(&wdata->refcount);
2125         rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2126                              NULL, cifs_writev_callback, wdata, 0);
2127
2128         if (rc == 0)
2129                 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2130         else
2131                 kref_put(&wdata->refcount, cifs_writedata_release);
2132
2133         /* send is done, unmap pages */
2134         for (i = 0; i < wdata->nr_pages; i++)
2135                 kunmap(wdata->pages[i]);
2136
2137 async_writev_out:
2138         cifs_small_buf_release(smb);
2139         kfree(iov);
2140         return rc;
2141 }
2142
2143 int
2144 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2145               unsigned int *nbytes, struct kvec *iov, int n_vec,
2146               const int long_op)
2147 {
2148         int rc = -EACCES;
2149         WRITE_REQ *pSMB = NULL;
2150         int wct;
2151         int smb_hdr_len;
2152         int resp_buf_type = 0;
2153         __u32 pid = io_parms->pid;
2154         __u16 netfid = io_parms->netfid;
2155         __u64 offset = io_parms->offset;
2156         struct cifs_tcon *tcon = io_parms->tcon;
2157         unsigned int count = io_parms->length;
2158
2159         *nbytes = 0;
2160
2161         cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2162
2163         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2164                 wct = 14;
2165         } else {
2166                 wct = 12;
2167                 if ((offset >> 32) > 0) {
2168                         /* can not handle big offset for old srv */
2169                         return -EIO;
2170                 }
2171         }
2172         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2173         if (rc)
2174                 return rc;
2175
2176         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2177         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2178
2179         /* tcon and ses pointer are checked in smb_init */
2180         if (tcon->ses->server == NULL)
2181                 return -ECONNABORTED;
2182
2183         pSMB->AndXCommand = 0xFF;       /* none */
2184         pSMB->Fid = netfid;
2185         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2186         if (wct == 14)
2187                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2188         pSMB->Reserved = 0xFFFFFFFF;
2189         pSMB->WriteMode = 0;
2190         pSMB->Remaining = 0;
2191
2192         pSMB->DataOffset =
2193             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2194
2195         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2196         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2197         /* header + 1 byte pad */
2198         smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2199         if (wct == 14)
2200                 inc_rfc1001_len(pSMB, count + 1);
2201         else /* wct == 12 */
2202                 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2203         if (wct == 14)
2204                 pSMB->ByteCount = cpu_to_le16(count + 1);
2205         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2206                 struct smb_com_writex_req *pSMBW =
2207                                 (struct smb_com_writex_req *)pSMB;
2208                 pSMBW->ByteCount = cpu_to_le16(count + 5);
2209         }
2210         iov[0].iov_base = pSMB;
2211         if (wct == 14)
2212                 iov[0].iov_len = smb_hdr_len + 4;
2213         else /* wct == 12 pad bigger by four bytes */
2214                 iov[0].iov_len = smb_hdr_len + 8;
2215
2216
2217         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2218                           long_op);
2219         cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2220         if (rc) {
2221                 cFYI(1, "Send error Write2 = %d", rc);
2222         } else if (resp_buf_type == 0) {
2223                 /* presumably this can not happen, but best to be safe */
2224                 rc = -EIO;
2225         } else {
2226                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2227                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2228                 *nbytes = (*nbytes) << 16;
2229                 *nbytes += le16_to_cpu(pSMBr->Count);
2230
2231                 /*
2232                  * Mask off high 16 bits when bytes written as returned by the
2233                  * server is greater than bytes requested by the client. OS/2
2234                  * servers are known to set incorrect CountHigh values.
2235                  */
2236                 if (*nbytes > count)
2237                         *nbytes &= 0xFFFF;
2238         }
2239
2240 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2241         if (resp_buf_type == CIFS_SMALL_BUFFER)
2242                 cifs_small_buf_release(iov[0].iov_base);
2243         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2244                 cifs_buf_release(iov[0].iov_base);
2245
2246         /* Note: On -EAGAIN error only caller can retry on handle based calls
2247                 since file handle passed in no longer valid */
2248
2249         return rc;
2250 }
2251
2252 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2253                const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2254                const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2255 {
2256         int rc = 0;
2257         LOCK_REQ *pSMB = NULL;
2258         struct kvec iov[2];
2259         int resp_buf_type;
2260         __u16 count;
2261
2262         cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2263
2264         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2265         if (rc)
2266                 return rc;
2267
2268         pSMB->Timeout = 0;
2269         pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2270         pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2271         pSMB->LockType = lock_type;
2272         pSMB->AndXCommand = 0xFF; /* none */
2273         pSMB->Fid = netfid; /* netfid stays le */
2274
2275         count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2276         inc_rfc1001_len(pSMB, count);
2277         pSMB->ByteCount = cpu_to_le16(count);
2278
2279         iov[0].iov_base = (char *)pSMB;
2280         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2281                          (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2282         iov[1].iov_base = (char *)buf;
2283         iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2284
2285         cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2286         rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2287         if (rc)
2288                 cFYI(1, "Send error in cifs_lockv = %d", rc);
2289
2290         return rc;
2291 }
2292
2293 int
2294 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2295             const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2296             const __u64 offset, const __u32 numUnlock,
2297             const __u32 numLock, const __u8 lockType,
2298             const bool waitFlag, const __u8 oplock_level)
2299 {
2300         int rc = 0;
2301         LOCK_REQ *pSMB = NULL;
2302 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2303         int bytes_returned;
2304         int flags = 0;
2305         __u16 count;
2306
2307         cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2308         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2309
2310         if (rc)
2311                 return rc;
2312
2313         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2314                 /* no response expected */
2315                 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2316                 pSMB->Timeout = 0;
2317         } else if (waitFlag) {
2318                 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2319                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2320         } else {
2321                 pSMB->Timeout = 0;
2322         }
2323
2324         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2325         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2326         pSMB->LockType = lockType;
2327         pSMB->OplockLevel = oplock_level;
2328         pSMB->AndXCommand = 0xFF;       /* none */
2329         pSMB->Fid = smb_file_id; /* netfid stays le */
2330
2331         if ((numLock != 0) || (numUnlock != 0)) {
2332                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2333                 /* BB where to store pid high? */
2334                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2335                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2336                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2337                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2338                 count = sizeof(LOCKING_ANDX_RANGE);
2339         } else {
2340                 /* oplock break */
2341                 count = 0;
2342         }
2343         inc_rfc1001_len(pSMB, count);
2344         pSMB->ByteCount = cpu_to_le16(count);
2345
2346         if (waitFlag) {
2347                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2348                         (struct smb_hdr *) pSMB, &bytes_returned);
2349                 cifs_small_buf_release(pSMB);
2350         } else {
2351                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2352                 /* SMB buffer freed by function above */
2353         }
2354         cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2355         if (rc)
2356                 cFYI(1, "Send error in Lock = %d", rc);
2357
2358         /* Note: On -EAGAIN error only caller can retry on handle based calls
2359         since file handle passed in no longer valid */
2360         return rc;
2361 }
2362
2363 int
2364 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2365                 const __u16 smb_file_id, const __u32 netpid,
2366                 const loff_t start_offset, const __u64 len,
2367                 struct file_lock *pLockData, const __u16 lock_type,
2368                 const bool waitFlag)
2369 {
2370         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2371         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2372         struct cifs_posix_lock *parm_data;
2373         int rc = 0;
2374         int timeout = 0;
2375         int bytes_returned = 0;
2376         int resp_buf_type = 0;
2377         __u16 params, param_offset, offset, byte_count, count;
2378         struct kvec iov[1];
2379
2380         cFYI(1, "Posix Lock");
2381
2382         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2383
2384         if (rc)
2385                 return rc;
2386
2387         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2388
2389         params = 6;
2390         pSMB->MaxSetupCount = 0;
2391         pSMB->Reserved = 0;
2392         pSMB->Flags = 0;
2393         pSMB->Reserved2 = 0;
2394         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2395         offset = param_offset + params;
2396
2397         count = sizeof(struct cifs_posix_lock);
2398         pSMB->MaxParameterCount = cpu_to_le16(2);
2399         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2400         pSMB->SetupCount = 1;
2401         pSMB->Reserved3 = 0;
2402         if (pLockData)
2403                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2404         else
2405                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2406         byte_count = 3 /* pad */  + params + count;
2407         pSMB->DataCount = cpu_to_le16(count);
2408         pSMB->ParameterCount = cpu_to_le16(params);
2409         pSMB->TotalDataCount = pSMB->DataCount;
2410         pSMB->TotalParameterCount = pSMB->ParameterCount;
2411         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2412         parm_data = (struct cifs_posix_lock *)
2413                         (((char *) &pSMB->hdr.Protocol) + offset);
2414
2415         parm_data->lock_type = cpu_to_le16(lock_type);
2416         if (waitFlag) {
2417                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2418                 parm_data->lock_flags = cpu_to_le16(1);
2419                 pSMB->Timeout = cpu_to_le32(-1);
2420         } else
2421                 pSMB->Timeout = 0;
2422
2423         parm_data->pid = cpu_to_le32(netpid);
2424         parm_data->start = cpu_to_le64(start_offset);
2425         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2426
2427         pSMB->DataOffset = cpu_to_le16(offset);
2428         pSMB->Fid = smb_file_id;
2429         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2430         pSMB->Reserved4 = 0;
2431         inc_rfc1001_len(pSMB, byte_count);
2432         pSMB->ByteCount = cpu_to_le16(byte_count);
2433         if (waitFlag) {
2434                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2435                         (struct smb_hdr *) pSMBr, &bytes_returned);
2436         } else {
2437                 iov[0].iov_base = (char *)pSMB;
2438                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2439                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2440                                 &resp_buf_type, timeout);
2441                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2442                                 not try to free it twice below on exit */
2443                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2444         }
2445
2446         if (rc) {
2447                 cFYI(1, "Send error in Posix Lock = %d", rc);
2448         } else if (pLockData) {
2449                 /* lock structure can be returned on get */
2450                 __u16 data_offset;
2451                 __u16 data_count;
2452                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2453
2454                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2455                         rc = -EIO;      /* bad smb */
2456                         goto plk_err_exit;
2457                 }
2458                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2459                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2460                 if (data_count < sizeof(struct cifs_posix_lock)) {
2461                         rc = -EIO;
2462                         goto plk_err_exit;
2463                 }
2464                 parm_data = (struct cifs_posix_lock *)
2465                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2466                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2467                         pLockData->fl_type = F_UNLCK;
2468                 else {
2469                         if (parm_data->lock_type ==
2470                                         __constant_cpu_to_le16(CIFS_RDLCK))
2471                                 pLockData->fl_type = F_RDLCK;
2472                         else if (parm_data->lock_type ==
2473                                         __constant_cpu_to_le16(CIFS_WRLCK))
2474                                 pLockData->fl_type = F_WRLCK;
2475
2476                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2477                         pLockData->fl_end = pLockData->fl_start +
2478                                         le64_to_cpu(parm_data->length) - 1;
2479                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2480                 }
2481         }
2482
2483 plk_err_exit:
2484         if (pSMB)
2485                 cifs_small_buf_release(pSMB);
2486
2487         if (resp_buf_type == CIFS_SMALL_BUFFER)
2488                 cifs_small_buf_release(iov[0].iov_base);
2489         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2490                 cifs_buf_release(iov[0].iov_base);
2491
2492         /* Note: On -EAGAIN error only caller can retry on handle based calls
2493            since file handle passed in no longer valid */
2494
2495         return rc;
2496 }
2497
2498
2499 int
2500 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2501 {
2502         int rc = 0;
2503         CLOSE_REQ *pSMB = NULL;
2504         cFYI(1, "In CIFSSMBClose");
2505
2506 /* do not retry on dead session on close */
2507         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2508         if (rc == -EAGAIN)
2509                 return 0;
2510         if (rc)
2511                 return rc;
2512
2513         pSMB->FileID = (__u16) smb_file_id;
2514         pSMB->LastWriteTime = 0xFFFFFFFF;
2515         pSMB->ByteCount = 0;
2516         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2517         cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2518         if (rc) {
2519                 if (rc != -EINTR) {
2520                         /* EINTR is expected when user ctl-c to kill app */
2521                         cERROR(1, "Send error in Close = %d", rc);
2522                 }
2523         }
2524
2525         /* Since session is dead, file will be closed on server already */
2526         if (rc == -EAGAIN)
2527                 rc = 0;
2528
2529         return rc;
2530 }
2531
2532 int
2533 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2534 {
2535         int rc = 0;
2536         FLUSH_REQ *pSMB = NULL;
2537         cFYI(1, "In CIFSSMBFlush");
2538
2539         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2540         if (rc)
2541                 return rc;
2542
2543         pSMB->FileID = (__u16) smb_file_id;
2544         pSMB->ByteCount = 0;
2545         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2546         cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2547         if (rc)
2548                 cERROR(1, "Send error in Flush = %d", rc);
2549
2550         return rc;
2551 }
2552
2553 int
2554 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2555               const char *fromName, const char *toName,
2556               const struct nls_table *nls_codepage, int remap)
2557 {
2558         int rc = 0;
2559         RENAME_REQ *pSMB = NULL;
2560         RENAME_RSP *pSMBr = NULL;
2561         int bytes_returned;
2562         int name_len, name_len2;
2563         __u16 count;
2564
2565         cFYI(1, "In CIFSSMBRename");
2566 renameRetry:
2567         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2568                       (void **) &pSMBr);
2569         if (rc)
2570                 return rc;
2571
2572         pSMB->BufferFormat = 0x04;
2573         pSMB->SearchAttributes =
2574             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2575                         ATTR_DIRECTORY);
2576
2577         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2578                 name_len =
2579                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2580                                        PATH_MAX, nls_codepage, remap);
2581                 name_len++;     /* trailing null */
2582                 name_len *= 2;
2583                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2584         /* protocol requires ASCII signature byte on Unicode string */
2585                 pSMB->OldFileName[name_len + 1] = 0x00;
2586                 name_len2 =
2587                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2588                                        toName, PATH_MAX, nls_codepage, remap);
2589                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2590                 name_len2 *= 2; /* convert to bytes */
2591         } else {        /* BB improve the check for buffer overruns BB */
2592                 name_len = strnlen(fromName, PATH_MAX);
2593                 name_len++;     /* trailing null */
2594                 strncpy(pSMB->OldFileName, fromName, name_len);
2595                 name_len2 = strnlen(toName, PATH_MAX);
2596                 name_len2++;    /* trailing null */
2597                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2598                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2599                 name_len2++;    /* trailing null */
2600                 name_len2++;    /* signature byte */
2601         }
2602
2603         count = 1 /* 1st signature byte */  + name_len + name_len2;
2604         inc_rfc1001_len(pSMB, count);
2605         pSMB->ByteCount = cpu_to_le16(count);
2606
2607         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2608                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2609         cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2610         if (rc)
2611                 cFYI(1, "Send error in rename = %d", rc);
2612
2613         cifs_buf_release(pSMB);
2614
2615         if (rc == -EAGAIN)
2616                 goto renameRetry;
2617
2618         return rc;
2619 }
2620
2621 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2622                 int netfid, const char *target_name,
2623                 const struct nls_table *nls_codepage, int remap)
2624 {
2625         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2626         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2627         struct set_file_rename *rename_info;
2628         char *data_offset;
2629         char dummy_string[30];
2630         int rc = 0;
2631         int bytes_returned = 0;
2632         int len_of_str;
2633         __u16 params, param_offset, offset, count, byte_count;
2634
2635         cFYI(1, "Rename to File by handle");
2636         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2637                         (void **) &pSMBr);
2638         if (rc)
2639                 return rc;
2640
2641         params = 6;
2642         pSMB->MaxSetupCount = 0;
2643         pSMB->Reserved = 0;
2644         pSMB->Flags = 0;
2645         pSMB->Timeout = 0;
2646         pSMB->Reserved2 = 0;
2647         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2648         offset = param_offset + params;
2649
2650         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2651         rename_info = (struct set_file_rename *) data_offset;
2652         pSMB->MaxParameterCount = cpu_to_le16(2);
2653         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2654         pSMB->SetupCount = 1;
2655         pSMB->Reserved3 = 0;
2656         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2657         byte_count = 3 /* pad */  + params;
2658         pSMB->ParameterCount = cpu_to_le16(params);
2659         pSMB->TotalParameterCount = pSMB->ParameterCount;
2660         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2661         pSMB->DataOffset = cpu_to_le16(offset);
2662         /* construct random name ".cifs_tmp<inodenum><mid>" */
2663         rename_info->overwrite = cpu_to_le32(1);
2664         rename_info->root_fid  = 0;
2665         /* unicode only call */
2666         if (target_name == NULL) {
2667                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2668                 len_of_str =
2669                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2670                                         dummy_string, 24, nls_codepage, remap);
2671         } else {
2672                 len_of_str =
2673                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2674                                         target_name, PATH_MAX, nls_codepage,
2675                                         remap);
2676         }
2677         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2678         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2679         byte_count += count;
2680         pSMB->DataCount = cpu_to_le16(count);
2681         pSMB->TotalDataCount = pSMB->DataCount;
2682         pSMB->Fid = netfid;
2683         pSMB->InformationLevel =
2684                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2685         pSMB->Reserved4 = 0;
2686         inc_rfc1001_len(pSMB, byte_count);
2687         pSMB->ByteCount = cpu_to_le16(byte_count);
2688         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2689                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2690         cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2691         if (rc)
2692                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2693
2694         cifs_buf_release(pSMB);
2695
2696         /* Note: On -EAGAIN error only caller can retry on handle based calls
2697                 since file handle passed in no longer valid */
2698
2699         return rc;
2700 }
2701
2702 int
2703 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2704             const char *fromName, const __u16 target_tid, const char *toName,
2705             const int flags, const struct nls_table *nls_codepage, int remap)
2706 {
2707         int rc = 0;
2708         COPY_REQ *pSMB = NULL;
2709         COPY_RSP *pSMBr = NULL;
2710         int bytes_returned;
2711         int name_len, name_len2;
2712         __u16 count;
2713
2714         cFYI(1, "In CIFSSMBCopy");
2715 copyRetry:
2716         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2717                         (void **) &pSMBr);
2718         if (rc)
2719                 return rc;
2720
2721         pSMB->BufferFormat = 0x04;
2722         pSMB->Tid2 = target_tid;
2723
2724         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2725
2726         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2727                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2728                                               fromName, PATH_MAX, nls_codepage,
2729                                               remap);
2730                 name_len++;     /* trailing null */
2731                 name_len *= 2;
2732                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2733                 /* protocol requires ASCII signature byte on Unicode string */
2734                 pSMB->OldFileName[name_len + 1] = 0x00;
2735                 name_len2 =
2736                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2737                                        toName, PATH_MAX, nls_codepage, remap);
2738                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2739                 name_len2 *= 2; /* convert to bytes */
2740         } else {        /* BB improve the check for buffer overruns BB */
2741                 name_len = strnlen(fromName, PATH_MAX);
2742                 name_len++;     /* trailing null */
2743                 strncpy(pSMB->OldFileName, fromName, name_len);
2744                 name_len2 = strnlen(toName, PATH_MAX);
2745                 name_len2++;    /* trailing null */
2746                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2747                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2748                 name_len2++;    /* trailing null */
2749                 name_len2++;    /* signature byte */
2750         }
2751
2752         count = 1 /* 1st signature byte */  + name_len + name_len2;
2753         inc_rfc1001_len(pSMB, count);
2754         pSMB->ByteCount = cpu_to_le16(count);
2755
2756         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2757                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2758         if (rc) {
2759                 cFYI(1, "Send error in copy = %d with %d files copied",
2760                         rc, le16_to_cpu(pSMBr->CopyCount));
2761         }
2762         cifs_buf_release(pSMB);
2763
2764         if (rc == -EAGAIN)
2765                 goto copyRetry;
2766
2767         return rc;
2768 }
2769
2770 int
2771 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2772                       const char *fromName, const char *toName,
2773                       const struct nls_table *nls_codepage)
2774 {
2775         TRANSACTION2_SPI_REQ *pSMB = NULL;
2776         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2777         char *data_offset;
2778         int name_len;
2779         int name_len_target;
2780         int rc = 0;
2781         int bytes_returned = 0;
2782         __u16 params, param_offset, offset, byte_count;
2783
2784         cFYI(1, "In Symlink Unix style");
2785 createSymLinkRetry:
2786         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2787                       (void **) &pSMBr);
2788         if (rc)
2789                 return rc;
2790
2791         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2792                 name_len =
2793                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2794                                     /* find define for this maxpathcomponent */
2795                                     PATH_MAX, nls_codepage);
2796                 name_len++;     /* trailing null */
2797                 name_len *= 2;
2798
2799         } else {        /* BB improve the check for buffer overruns BB */
2800                 name_len = strnlen(fromName, PATH_MAX);
2801                 name_len++;     /* trailing null */
2802                 strncpy(pSMB->FileName, fromName, name_len);
2803         }
2804         params = 6 + name_len;
2805         pSMB->MaxSetupCount = 0;
2806         pSMB->Reserved = 0;
2807         pSMB->Flags = 0;
2808         pSMB->Timeout = 0;
2809         pSMB->Reserved2 = 0;
2810         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2811                                 InformationLevel) - 4;
2812         offset = param_offset + params;
2813
2814         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2815         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2816                 name_len_target =
2817                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2818                                     /* find define for this maxpathcomponent */
2819                                     , nls_codepage);
2820                 name_len_target++;      /* trailing null */
2821                 name_len_target *= 2;
2822         } else {        /* BB improve the check for buffer overruns BB */
2823                 name_len_target = strnlen(toName, PATH_MAX);
2824                 name_len_target++;      /* trailing null */
2825                 strncpy(data_offset, toName, name_len_target);
2826         }
2827
2828         pSMB->MaxParameterCount = cpu_to_le16(2);
2829         /* BB find exact max on data count below from sess */
2830         pSMB->MaxDataCount = cpu_to_le16(1000);
2831         pSMB->SetupCount = 1;
2832         pSMB->Reserved3 = 0;
2833         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2834         byte_count = 3 /* pad */  + params + name_len_target;
2835         pSMB->DataCount = cpu_to_le16(name_len_target);
2836         pSMB->ParameterCount = cpu_to_le16(params);
2837         pSMB->TotalDataCount = pSMB->DataCount;
2838         pSMB->TotalParameterCount = pSMB->ParameterCount;
2839         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2840         pSMB->DataOffset = cpu_to_le16(offset);
2841         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2842         pSMB->Reserved4 = 0;
2843         inc_rfc1001_len(pSMB, byte_count);
2844         pSMB->ByteCount = cpu_to_le16(byte_count);
2845         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2846                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2847         cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2848         if (rc)
2849                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2850
2851         cifs_buf_release(pSMB);
2852
2853         if (rc == -EAGAIN)
2854                 goto createSymLinkRetry;
2855
2856         return rc;
2857 }
2858
2859 int
2860 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2861                        const char *fromName, const char *toName,
2862                        const struct nls_table *nls_codepage, int remap)
2863 {
2864         TRANSACTION2_SPI_REQ *pSMB = NULL;
2865         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2866         char *data_offset;
2867         int name_len;
2868         int name_len_target;
2869         int rc = 0;
2870         int bytes_returned = 0;
2871         __u16 params, param_offset, offset, byte_count;
2872
2873         cFYI(1, "In Create Hard link Unix style");
2874 createHardLinkRetry:
2875         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2876                       (void **) &pSMBr);
2877         if (rc)
2878                 return rc;
2879
2880         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2881                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2882                                               PATH_MAX, nls_codepage, remap);
2883                 name_len++;     /* trailing null */
2884                 name_len *= 2;
2885
2886         } else {        /* BB improve the check for buffer overruns BB */
2887                 name_len = strnlen(toName, PATH_MAX);
2888                 name_len++;     /* trailing null */
2889                 strncpy(pSMB->FileName, toName, name_len);
2890         }
2891         params = 6 + name_len;
2892         pSMB->MaxSetupCount = 0;
2893         pSMB->Reserved = 0;
2894         pSMB->Flags = 0;
2895         pSMB->Timeout = 0;
2896         pSMB->Reserved2 = 0;
2897         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2898                                 InformationLevel) - 4;
2899         offset = param_offset + params;
2900
2901         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2902         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2903                 name_len_target =
2904                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2905                                        PATH_MAX, nls_codepage, remap);
2906                 name_len_target++;      /* trailing null */
2907                 name_len_target *= 2;
2908         } else {        /* BB improve the check for buffer overruns BB */
2909                 name_len_target = strnlen(fromName, PATH_MAX);
2910                 name_len_target++;      /* trailing null */
2911                 strncpy(data_offset, fromName, name_len_target);
2912         }
2913
2914         pSMB->MaxParameterCount = cpu_to_le16(2);
2915         /* BB find exact max on data count below from sess*/
2916         pSMB->MaxDataCount = cpu_to_le16(1000);
2917         pSMB->SetupCount = 1;
2918         pSMB->Reserved3 = 0;
2919         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2920         byte_count = 3 /* pad */  + params + name_len_target;
2921         pSMB->ParameterCount = cpu_to_le16(params);
2922         pSMB->TotalParameterCount = pSMB->ParameterCount;
2923         pSMB->DataCount = cpu_to_le16(name_len_target);
2924         pSMB->TotalDataCount = pSMB->DataCount;
2925         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2926         pSMB->DataOffset = cpu_to_le16(offset);
2927         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2928         pSMB->Reserved4 = 0;
2929         inc_rfc1001_len(pSMB, byte_count);
2930         pSMB->ByteCount = cpu_to_le16(byte_count);
2931         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2932                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2933         cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2934         if (rc)
2935                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2936
2937         cifs_buf_release(pSMB);
2938         if (rc == -EAGAIN)
2939                 goto createHardLinkRetry;
2940
2941         return rc;
2942 }
2943
2944 int
2945 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2946                    const char *fromName, const char *toName,
2947                    const struct nls_table *nls_codepage, int remap)
2948 {
2949         int rc = 0;
2950         NT_RENAME_REQ *pSMB = NULL;
2951         RENAME_RSP *pSMBr = NULL;
2952         int bytes_returned;
2953         int name_len, name_len2;
2954         __u16 count;
2955
2956         cFYI(1, "In CIFSCreateHardLink");
2957 winCreateHardLinkRetry:
2958
2959         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2960                       (void **) &pSMBr);
2961         if (rc)
2962                 return rc;
2963
2964         pSMB->SearchAttributes =
2965             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2966                         ATTR_DIRECTORY);
2967         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2968         pSMB->ClusterCount = 0;
2969
2970         pSMB->BufferFormat = 0x04;
2971
2972         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2973                 name_len =
2974                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2975                                        PATH_MAX, nls_codepage, remap);
2976                 name_len++;     /* trailing null */
2977                 name_len *= 2;
2978
2979                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2980                 pSMB->OldFileName[name_len] = 0x04;
2981                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2982                 name_len2 =
2983                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2984                                        toName, PATH_MAX, nls_codepage, remap);
2985                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2986                 name_len2 *= 2; /* convert to bytes */
2987         } else {        /* BB improve the check for buffer overruns BB */
2988                 name_len = strnlen(fromName, PATH_MAX);
2989                 name_len++;     /* trailing null */
2990                 strncpy(pSMB->OldFileName, fromName, name_len);
2991                 name_len2 = strnlen(toName, PATH_MAX);
2992                 name_len2++;    /* trailing null */
2993                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2994                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2995                 name_len2++;    /* trailing null */
2996                 name_len2++;    /* signature byte */
2997         }
2998
2999         count = 1 /* string type byte */  + name_len + name_len2;
3000         inc_rfc1001_len(pSMB, count);
3001         pSMB->ByteCount = cpu_to_le16(count);
3002
3003         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3004                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3005         cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3006         if (rc)
3007                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3008
3009         cifs_buf_release(pSMB);
3010         if (rc == -EAGAIN)
3011                 goto winCreateHardLinkRetry;
3012
3013         return rc;
3014 }
3015
3016 int
3017 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3018                         const unsigned char *searchName, char **symlinkinfo,
3019                         const struct nls_table *nls_codepage)
3020 {
3021 /* SMB_QUERY_FILE_UNIX_LINK */
3022         TRANSACTION2_QPI_REQ *pSMB = NULL;
3023         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3024         int rc = 0;
3025         int bytes_returned;
3026         int name_len;
3027         __u16 params, byte_count;
3028         char *data_start;
3029
3030         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3031
3032 querySymLinkRetry:
3033         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3034                       (void **) &pSMBr);
3035         if (rc)
3036                 return rc;
3037
3038         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3039                 name_len =
3040                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3041                                         PATH_MAX, nls_codepage);
3042                 name_len++;     /* trailing null */
3043                 name_len *= 2;
3044         } else {        /* BB improve the check for buffer overruns BB */
3045                 name_len = strnlen(searchName, PATH_MAX);
3046                 name_len++;     /* trailing null */
3047                 strncpy(pSMB->FileName, searchName, name_len);
3048         }
3049
3050         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3051         pSMB->TotalDataCount = 0;
3052         pSMB->MaxParameterCount = cpu_to_le16(2);
3053         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3054         pSMB->MaxSetupCount = 0;
3055         pSMB->Reserved = 0;
3056         pSMB->Flags = 0;
3057         pSMB->Timeout = 0;
3058         pSMB->Reserved2 = 0;
3059         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3060         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3061         pSMB->DataCount = 0;
3062         pSMB->DataOffset = 0;
3063         pSMB->SetupCount = 1;
3064         pSMB->Reserved3 = 0;
3065         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3066         byte_count = params + 1 /* pad */ ;
3067         pSMB->TotalParameterCount = cpu_to_le16(params);
3068         pSMB->ParameterCount = pSMB->TotalParameterCount;
3069         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3070         pSMB->Reserved4 = 0;
3071         inc_rfc1001_len(pSMB, byte_count);
3072         pSMB->ByteCount = cpu_to_le16(byte_count);
3073
3074         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3075                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3076         if (rc) {
3077                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3078         } else {
3079                 /* decode response */
3080
3081                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3082                 /* BB also check enough total bytes returned */
3083                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3084                         rc = -EIO;
3085                 else {
3086                         bool is_unicode;
3087                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3088
3089                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3090                                            le16_to_cpu(pSMBr->t2.DataOffset);
3091
3092                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3093                                 is_unicode = true;
3094                         else
3095                                 is_unicode = false;
3096
3097                         /* BB FIXME investigate remapping reserved chars here */
3098                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3099                                         count, is_unicode, nls_codepage);
3100                         if (!*symlinkinfo)
3101                                 rc = -ENOMEM;
3102                 }
3103         }
3104         cifs_buf_release(pSMB);
3105         if (rc == -EAGAIN)
3106                 goto querySymLinkRetry;
3107         return rc;
3108 }
3109
3110 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3111 /*
3112  *      Recent Windows versions now create symlinks more frequently
3113  *      and they use the "reparse point" mechanism below.  We can of course
3114  *      do symlinks nicely to Samba and other servers which support the
3115  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3116  *      "MF" symlinks optionally, but for recent Windows we really need to
3117  *      reenable the code below and fix the cifs_symlink callers to handle this.
3118  *      In the interim this code has been moved to its own config option so
3119  *      it is not compiled in by default until callers fixed up and more tested.
3120  */
3121 int
3122 CIFSSMBQueryReparseLinkInfo(const unsigned int xid, struct cifs_tcon *tcon,
3123                         const unsigned char *searchName,
3124                         char *symlinkinfo, const int buflen, __u16 fid,
3125                         const struct nls_table *nls_codepage)
3126 {
3127         int rc = 0;
3128         int bytes_returned;
3129         struct smb_com_transaction_ioctl_req *pSMB;
3130         struct smb_com_transaction_ioctl_rsp *pSMBr;
3131
3132         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3133         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3134                       (void **) &pSMBr);
3135         if (rc)
3136                 return rc;
3137
3138         pSMB->TotalParameterCount = 0 ;
3139         pSMB->TotalDataCount = 0;
3140         pSMB->MaxParameterCount = cpu_to_le32(2);
3141         /* BB find exact data count max from sess structure BB */
3142         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3143         pSMB->MaxSetupCount = 4;
3144         pSMB->Reserved = 0;
3145         pSMB->ParameterOffset = 0;
3146         pSMB->DataCount = 0;
3147         pSMB->DataOffset = 0;
3148         pSMB->SetupCount = 4;
3149         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3150         pSMB->ParameterCount = pSMB->TotalParameterCount;
3151         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3152         pSMB->IsFsctl = 1; /* FSCTL */
3153         pSMB->IsRootFlag = 0;
3154         pSMB->Fid = fid; /* file handle always le */
3155         pSMB->ByteCount = 0;
3156
3157         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3158                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3159         if (rc) {
3160                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3161         } else {                /* decode response */
3162                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3163                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3164                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3165                         /* BB also check enough total bytes returned */
3166                         rc = -EIO;      /* bad smb */
3167                         goto qreparse_out;
3168                 }
3169                 if (data_count && (data_count < 2048)) {
3170                         char *end_of_smb = 2 /* sizeof byte count */ +
3171                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3172
3173                         struct reparse_data *reparse_buf =
3174                                                 (struct reparse_data *)
3175                                                 ((char *)&pSMBr->hdr.Protocol
3176                                                                  + data_offset);
3177                         if ((char *)reparse_buf >= end_of_smb) {
3178                                 rc = -EIO;
3179                                 goto qreparse_out;
3180                         }
3181                         if ((reparse_buf->LinkNamesBuf +
3182                                 reparse_buf->TargetNameOffset +
3183                                 reparse_buf->TargetNameLen) > end_of_smb) {
3184                                 cFYI(1, "reparse buf beyond SMB");
3185                                 rc = -EIO;
3186                                 goto qreparse_out;
3187                         }
3188
3189                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3190                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3191                                                 (reparse_buf->LinkNamesBuf +
3192                                                 reparse_buf->TargetNameOffset),
3193                                                 buflen,
3194                                                 reparse_buf->TargetNameLen,
3195                                                 nls_codepage, 0);
3196                         } else { /* ASCII names */
3197                                 strncpy(symlinkinfo,
3198                                         reparse_buf->LinkNamesBuf +
3199                                         reparse_buf->TargetNameOffset,
3200                                         min_t(const int, buflen,
3201                                            reparse_buf->TargetNameLen));
3202                         }
3203                 } else {
3204                         rc = -EIO;
3205                         cFYI(1, "Invalid return data count on "
3206                                  "get reparse info ioctl");
3207                 }
3208                 symlinkinfo[buflen] = 0; /* just in case so the caller
3209                                         does not go off the end of the buffer */
3210                 cFYI(1, "readlink result - %s", symlinkinfo);
3211         }
3212
3213 qreparse_out:
3214         cifs_buf_release(pSMB);
3215
3216         /* Note: On -EAGAIN error only caller can retry on handle based calls
3217                 since file handle passed in no longer valid */
3218
3219         return rc;
3220 }
3221 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3222
3223 #ifdef CONFIG_CIFS_POSIX
3224
3225 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3226 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3227                              struct cifs_posix_ace *cifs_ace)
3228 {
3229         /* u8 cifs fields do not need le conversion */
3230         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3231         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3232         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3233         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3234
3235         return;
3236 }
3237
3238 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3239 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3240                                const int acl_type, const int size_of_data_area)
3241 {
3242         int size =  0;
3243         int i;
3244         __u16 count;
3245         struct cifs_posix_ace *pACE;
3246         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3247         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3248
3249         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3250                 return -EOPNOTSUPP;
3251
3252         if (acl_type & ACL_TYPE_ACCESS) {
3253                 count = le16_to_cpu(cifs_acl->access_entry_count);
3254                 pACE = &cifs_acl->ace_array[0];
3255                 size = sizeof(struct cifs_posix_acl);
3256                 size += sizeof(struct cifs_posix_ace) * count;
3257                 /* check if we would go beyond end of SMB */
3258                 if (size_of_data_area < size) {
3259                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3260                                 size_of_data_area, size);
3261                         return -EINVAL;
3262                 }
3263         } else if (acl_type & ACL_TYPE_DEFAULT) {
3264                 count = le16_to_cpu(cifs_acl->access_entry_count);
3265                 size = sizeof(struct cifs_posix_acl);
3266                 size += sizeof(struct cifs_posix_ace) * count;
3267 /* skip past access ACEs to get to default ACEs */
3268                 pACE = &cifs_acl->ace_array[count];
3269                 count = le16_to_cpu(cifs_acl->default_entry_count);
3270                 size += sizeof(struct cifs_posix_ace) * count;
3271                 /* check if we would go beyond end of SMB */
3272                 if (size_of_data_area < size)
3273                         return -EINVAL;
3274         } else {
3275                 /* illegal type */
3276                 return -EINVAL;
3277         }
3278
3279         size = posix_acl_xattr_size(count);
3280         if ((buflen == 0) || (local_acl == NULL)) {
3281                 /* used to query ACL EA size */
3282         } else if (size > buflen) {
3283                 return -ERANGE;
3284         } else /* buffer big enough */ {
3285                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3286                 for (i = 0; i < count ; i++) {
3287                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3288                         pACE++;
3289                 }
3290         }
3291         return size;
3292 }
3293
3294 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3295                                      const posix_acl_xattr_entry *local_ace)
3296 {
3297         __u16 rc = 0; /* 0 = ACL converted ok */
3298
3299         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3300         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3301         /* BB is there a better way to handle the large uid? */
3302         if (local_ace->e_id == cpu_to_le32(-1)) {
3303         /* Probably no need to le convert -1 on any arch but can not hurt */
3304                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3305         } else
3306                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3307         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3308         return rc;
3309 }
3310
3311 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3312 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3313                                const int buflen, const int acl_type)
3314 {
3315         __u16 rc = 0;
3316         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3317         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3318         int count;
3319         int i;
3320
3321         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3322                 return 0;
3323
3324         count = posix_acl_xattr_count((size_t)buflen);
3325         cFYI(1, "setting acl with %d entries from buf of length %d and "
3326                 "version of %d",
3327                 count, buflen, le32_to_cpu(local_acl->a_version));
3328         if (le32_to_cpu(local_acl->a_version) != 2) {
3329                 cFYI(1, "unknown POSIX ACL version %d",
3330                      le32_to_cpu(local_acl->a_version));
3331                 return 0;
3332         }
3333         cifs_acl->version = cpu_to_le16(1);
3334         if (acl_type == ACL_TYPE_ACCESS)
3335                 cifs_acl->access_entry_count = cpu_to_le16(count);
3336         else if (acl_type == ACL_TYPE_DEFAULT)
3337                 cifs_acl->default_entry_count = cpu_to_le16(count);
3338         else {
3339                 cFYI(1, "unknown ACL type %d", acl_type);
3340                 return 0;
3341         }
3342         for (i = 0; i < count; i++) {
3343                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3344                                         &local_acl->a_entries[i]);
3345                 if (rc != 0) {
3346                         /* ACE not converted */
3347                         break;
3348                 }
3349         }
3350         if (rc == 0) {
3351                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3352                 rc += sizeof(struct cifs_posix_acl);
3353                 /* BB add check to make sure ACL does not overflow SMB */
3354         }
3355         return rc;
3356 }
3357
3358 int
3359 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3360                    const unsigned char *searchName,
3361                    char *acl_inf, const int buflen, const int acl_type,
3362                    const struct nls_table *nls_codepage, int remap)
3363 {
3364 /* SMB_QUERY_POSIX_ACL */
3365         TRANSACTION2_QPI_REQ *pSMB = NULL;
3366         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3367         int rc = 0;
3368         int bytes_returned;
3369         int name_len;
3370         __u16 params, byte_count;
3371
3372         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3373
3374 queryAclRetry:
3375         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3376                 (void **) &pSMBr);
3377         if (rc)
3378                 return rc;
3379
3380         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3381                 name_len =
3382                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3383                                            searchName, PATH_MAX, nls_codepage,
3384                                            remap);
3385                 name_len++;     /* trailing null */
3386                 name_len *= 2;
3387                 pSMB->FileName[name_len] = 0;
3388                 pSMB->FileName[name_len+1] = 0;
3389         } else {        /* BB improve the check for buffer overruns BB */
3390                 name_len = strnlen(searchName, PATH_MAX);
3391                 name_len++;     /* trailing null */
3392                 strncpy(pSMB->FileName, searchName, name_len);
3393         }
3394
3395         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3396         pSMB->TotalDataCount = 0;
3397         pSMB->MaxParameterCount = cpu_to_le16(2);
3398         /* BB find exact max data count below from sess structure BB */
3399         pSMB->MaxDataCount = cpu_to_le16(4000);
3400         pSMB->MaxSetupCount = 0;
3401         pSMB->Reserved = 0;
3402         pSMB->Flags = 0;
3403         pSMB->Timeout = 0;
3404         pSMB->Reserved2 = 0;
3405         pSMB->ParameterOffset = cpu_to_le16(
3406                 offsetof(struct smb_com_transaction2_qpi_req,
3407                          InformationLevel) - 4);
3408         pSMB->DataCount = 0;
3409         pSMB->DataOffset = 0;
3410         pSMB->SetupCount = 1;
3411         pSMB->Reserved3 = 0;
3412         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3413         byte_count = params + 1 /* pad */ ;
3414         pSMB->TotalParameterCount = cpu_to_le16(params);
3415         pSMB->ParameterCount = pSMB->TotalParameterCount;
3416         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3417         pSMB->Reserved4 = 0;
3418         inc_rfc1001_len(pSMB, byte_count);
3419         pSMB->ByteCount = cpu_to_le16(byte_count);
3420
3421         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3422                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3423         cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3424         if (rc) {
3425                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3426         } else {
3427                 /* decode response */
3428
3429                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3430                 /* BB also check enough total bytes returned */
3431                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3432                         rc = -EIO;      /* bad smb */
3433                 else {
3434                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3435                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3436                         rc = cifs_copy_posix_acl(acl_inf,
3437                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3438                                 buflen, acl_type, count);
3439                 }
3440         }
3441         cifs_buf_release(pSMB);
3442         if (rc == -EAGAIN)
3443                 goto queryAclRetry;
3444         return rc;
3445 }
3446
3447 int
3448 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3449                    const unsigned char *fileName,
3450                    const char *local_acl, const int buflen,
3451                    const int acl_type,
3452                    const struct nls_table *nls_codepage, int remap)
3453 {
3454         struct smb_com_transaction2_spi_req *pSMB = NULL;
3455         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3456         char *parm_data;
3457         int name_len;
3458         int rc = 0;
3459         int bytes_returned = 0;
3460         __u16 params, byte_count, data_count, param_offset, offset;
3461
3462         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3463 setAclRetry:
3464         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3465                       (void **) &pSMBr);
3466         if (rc)
3467                 return rc;
3468         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3469                 name_len =
3470                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3471                                            PATH_MAX, nls_codepage, remap);
3472                 name_len++;     /* trailing null */
3473                 name_len *= 2;
3474         } else {        /* BB improve the check for buffer overruns BB */
3475                 name_len = strnlen(fileName, PATH_MAX);
3476                 name_len++;     /* trailing null */
3477                 strncpy(pSMB->FileName, fileName, name_len);
3478         }
3479         params = 6 + name_len;
3480         pSMB->MaxParameterCount = cpu_to_le16(2);
3481         /* BB find max SMB size from sess */
3482         pSMB->MaxDataCount = cpu_to_le16(1000);
3483         pSMB->MaxSetupCount = 0;
3484         pSMB->Reserved = 0;
3485         pSMB->Flags = 0;
3486         pSMB->Timeout = 0;
3487         pSMB->Reserved2 = 0;
3488         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3489                                 InformationLevel) - 4;
3490         offset = param_offset + params;
3491         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3492         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3493
3494         /* convert to on the wire format for POSIX ACL */
3495         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3496
3497         if (data_count == 0) {
3498                 rc = -EOPNOTSUPP;
3499                 goto setACLerrorExit;
3500         }
3501         pSMB->DataOffset = cpu_to_le16(offset);
3502         pSMB->SetupCount = 1;
3503         pSMB->Reserved3 = 0;
3504         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3505         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3506         byte_count = 3 /* pad */  + params + data_count;
3507         pSMB->DataCount = cpu_to_le16(data_count);
3508         pSMB->TotalDataCount = pSMB->DataCount;
3509         pSMB->ParameterCount = cpu_to_le16(params);
3510         pSMB->TotalParameterCount = pSMB->ParameterCount;
3511         pSMB->Reserved4 = 0;
3512         inc_rfc1001_len(pSMB, byte_count);
3513         pSMB->ByteCount = cpu_to_le16(byte_count);
3514         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3515                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3516         if (rc)
3517                 cFYI(1, "Set POSIX ACL returned %d", rc);
3518
3519 setACLerrorExit:
3520         cifs_buf_release(pSMB);
3521         if (rc == -EAGAIN)
3522                 goto setAclRetry;
3523         return rc;
3524 }
3525
3526 /* BB fix tabs in this function FIXME BB */
3527 int
3528 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3529                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3530 {
3531         int rc = 0;
3532         struct smb_t2_qfi_req *pSMB = NULL;
3533         struct smb_t2_qfi_rsp *pSMBr = NULL;
3534         int bytes_returned;
3535         __u16 params, byte_count;
3536
3537         cFYI(1, "In GetExtAttr");
3538         if (tcon == NULL)
3539                 return -ENODEV;
3540
3541 GetExtAttrRetry:
3542         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3543                         (void **) &pSMBr);
3544         if (rc)
3545                 return rc;
3546
3547         params = 2 /* level */ + 2 /* fid */;
3548         pSMB->t2.TotalDataCount = 0;
3549         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3550         /* BB find exact max data count below from sess structure BB */
3551         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3552         pSMB->t2.MaxSetupCount = 0;
3553         pSMB->t2.Reserved = 0;
3554         pSMB->t2.Flags = 0;
3555         pSMB->t2.Timeout = 0;
3556         pSMB->t2.Reserved2 = 0;
3557         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3558                                                Fid) - 4);
3559         pSMB->t2.DataCount = 0;
3560         pSMB->t2.DataOffset = 0;
3561         pSMB->t2.SetupCount = 1;
3562         pSMB->t2.Reserved3 = 0;
3563         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3564         byte_count = params + 1 /* pad */ ;
3565         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3566         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3567         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3568         pSMB->Pad = 0;
3569         pSMB->Fid = netfid;
3570         inc_rfc1001_len(pSMB, byte_count);
3571         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3572
3573         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3574                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3575         if (rc) {
3576                 cFYI(1, "error %d in GetExtAttr", rc);
3577         } else {
3578                 /* decode response */
3579                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3580                 /* BB also check enough total bytes returned */
3581                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3582                         /* If rc should we check for EOPNOSUPP and
3583                            disable the srvino flag? or in caller? */
3584                         rc = -EIO;      /* bad smb */
3585                 else {
3586                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3587                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3588                         struct file_chattr_info *pfinfo;
3589                         /* BB Do we need a cast or hash here ? */
3590                         if (count != 16) {
3591                                 cFYI(1, "Illegal size ret in GetExtAttr");
3592                                 rc = -EIO;
3593                                 goto GetExtAttrOut;
3594                         }
3595                         pfinfo = (struct file_chattr_info *)
3596                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3597                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3598                         *pMask = le64_to_cpu(pfinfo->mask);
3599                 }
3600         }
3601 GetExtAttrOut:
3602         cifs_buf_release(pSMB);
3603         if (rc == -EAGAIN)
3604                 goto GetExtAttrRetry;
3605         return rc;
3606 }
3607
3608 #endif /* CONFIG_POSIX */
3609
3610 #ifdef CONFIG_CIFS_ACL
3611 /*
3612  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3613  * all NT TRANSACTS that we init here have total parm and data under about 400
3614  * bytes (to fit in small cifs buffer size), which is the case so far, it
3615  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3616  * returned setup area) and MaxParameterCount (returned parms size) must be set
3617  * by caller
3618  */
3619 static int
3620 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3621                    const int parm_len, struct cifs_tcon *tcon,
3622                    void **ret_buf)
3623 {
3624         int rc;
3625         __u32 temp_offset;
3626         struct smb_com_ntransact_req *pSMB;
3627
3628         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3629                                 (void **)&pSMB);
3630         if (rc)
3631                 return rc;
3632         *ret_buf = (void *)pSMB;
3633         pSMB->Reserved = 0;
3634         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3635         pSMB->TotalDataCount  = 0;
3636         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3637         pSMB->ParameterCount = pSMB->TotalParameterCount;
3638         pSMB->DataCount  = pSMB->TotalDataCount;
3639         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3640                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3641         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3642         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3643         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3644         pSMB->SubCommand = cpu_to_le16(sub_command);
3645         return 0;
3646 }
3647
3648 static int
3649 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3650                    __u32 *pparmlen, __u32 *pdatalen)
3651 {
3652         char *end_of_smb;
3653         __u32 data_count, data_offset, parm_count, parm_offset;
3654         struct smb_com_ntransact_rsp *pSMBr;
3655         u16 bcc;
3656
3657         *pdatalen = 0;
3658         *pparmlen = 0;
3659
3660         if (buf == NULL)
3661                 return -EINVAL;
3662
3663         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3664
3665         bcc = get_bcc(&pSMBr->hdr);
3666         end_of_smb = 2 /* sizeof byte count */ + bcc +
3667                         (char *)&pSMBr->ByteCount;
3668
3669         data_offset = le32_to_cpu(pSMBr->DataOffset);
3670         data_count = le32_to_cpu(pSMBr->DataCount);
3671         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3672         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3673
3674         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3675         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3676
3677         /* should we also check that parm and data areas do not overlap? */
3678         if (*ppparm > end_of_smb) {
3679                 cFYI(1, "parms start after end of smb");
3680                 return -EINVAL;
3681         } else if (parm_count + *ppparm > end_of_smb) {
3682                 cFYI(1, "parm end after end of smb");
3683                 return -EINVAL;
3684         } else if (*ppdata > end_of_smb) {
3685                 cFYI(1, "data starts after end of smb");
3686                 return -EINVAL;
3687         } else if (data_count + *ppdata > end_of_smb) {
3688                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3689                         *ppdata, data_count, (data_count + *ppdata),
3690                         end_of_smb, pSMBr);
3691                 return -EINVAL;
3692         } else if (parm_count + data_count > bcc) {
3693                 cFYI(1, "parm count and data count larger than SMB");
3694                 return -EINVAL;
3695         }
3696         *pdatalen = data_count;
3697         *pparmlen = parm_count;
3698         return 0;
3699 }
3700
3701 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3702 int
3703 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3704                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3705 {
3706         int rc = 0;
3707         int buf_type = 0;
3708         QUERY_SEC_DESC_REQ *pSMB;
3709         struct kvec iov[1];
3710
3711         cFYI(1, "GetCifsACL");
3712
3713         *pbuflen = 0;
3714         *acl_inf = NULL;
3715
3716         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3717                         8 /* parm len */, tcon, (void **) &pSMB);
3718         if (rc)
3719                 return rc;
3720
3721         pSMB->MaxParameterCount = cpu_to_le32(4);
3722         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3723         pSMB->MaxSetupCount = 0;
3724         pSMB->Fid = fid; /* file handle always le */
3725         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3726                                      CIFS_ACL_DACL);
3727         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3728         inc_rfc1001_len(pSMB, 11);
3729         iov[0].iov_base = (char *)pSMB;
3730         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3731
3732         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3733                          0);
3734         cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3735         if (rc) {
3736                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3737         } else {                /* decode response */
3738                 __le32 *parm;
3739                 __u32 parm_len;
3740                 __u32 acl_len;
3741                 struct smb_com_ntransact_rsp *pSMBr;
3742                 char *pdata;
3743
3744 /* validate_nttransact */
3745                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3746                                         &pdata, &parm_len, pbuflen);
3747                 if (rc)
3748                         goto qsec_out;
3749                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3750
3751                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3752
3753                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3754                         rc = -EIO;      /* bad smb */
3755                         *pbuflen = 0;
3756                         goto qsec_out;
3757                 }
3758
3759 /* BB check that data area is minimum length and as big as acl_len */
3760
3761                 acl_len = le32_to_cpu(*parm);
3762                 if (acl_len != *pbuflen) {
3763                         cERROR(1, "acl length %d does not match %d",
3764                                    acl_len, *pbuflen);
3765                         if (*pbuflen > acl_len)
3766                                 *pbuflen = acl_len;
3767                 }
3768
3769                 /* check if buffer is big enough for the acl
3770                    header followed by the smallest SID */
3771                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3772                     (*pbuflen >= 64 * 1024)) {
3773                         cERROR(1, "bad acl length %d", *pbuflen);
3774                         rc = -EINVAL;
3775                         *pbuflen = 0;
3776                 } else {
3777                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3778                         if (*acl_inf == NULL) {
3779                                 *pbuflen = 0;
3780                                 rc = -ENOMEM;
3781                         }
3782                         memcpy(*acl_inf, pdata, *pbuflen);
3783                 }
3784         }
3785 qsec_out:
3786         if (buf_type == CIFS_SMALL_BUFFER)
3787                 cifs_small_buf_release(iov[0].iov_base);
3788         else if (buf_type == CIFS_LARGE_BUFFER)
3789                 cifs_buf_release(iov[0].iov_base);
3790 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3791         return rc;
3792 }
3793
3794 int
3795 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3796                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3797 {
3798         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3799         int rc = 0;
3800         int bytes_returned = 0;
3801         SET_SEC_DESC_REQ *pSMB = NULL;
3802         void *pSMBr;
3803
3804 setCifsAclRetry:
3805         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3806         if (rc)
3807                 return rc;
3808
3809         pSMB->MaxSetupCount = 0;
3810         pSMB->Reserved = 0;
3811
3812         param_count = 8;
3813         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3814         data_count = acllen;
3815         data_offset = param_offset + param_count;
3816         byte_count = 3 /* pad */  + param_count;
3817
3818         pSMB->DataCount = cpu_to_le32(data_count);
3819         pSMB->TotalDataCount = pSMB->DataCount;
3820         pSMB->MaxParameterCount = cpu_to_le32(4);
3821         pSMB->MaxDataCount = cpu_to_le32(16384);
3822         pSMB->ParameterCount = cpu_to_le32(param_count);
3823         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3824         pSMB->TotalParameterCount = pSMB->ParameterCount;
3825         pSMB->DataOffset = cpu_to_le32(data_offset);
3826         pSMB->SetupCount = 0;
3827         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3828         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3829
3830         pSMB->Fid = fid; /* file handle always le */
3831         pSMB->Reserved2 = 0;
3832         pSMB->AclFlags = cpu_to_le32(aclflag);
3833
3834         if (pntsd && acllen) {
3835                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3836                                 data_offset, pntsd, acllen);
3837                 inc_rfc1001_len(pSMB, byte_count + data_count);
3838         } else
3839                 inc_rfc1001_len(pSMB, byte_count);
3840
3841         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3842                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3843
3844         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3845         if (rc)
3846                 cFYI(1, "Set CIFS ACL returned %d", rc);
3847         cifs_buf_release(pSMB);
3848
3849         if (rc == -EAGAIN)
3850                 goto setCifsAclRetry;
3851
3852         return (rc);
3853 }
3854
3855 #endif /* CONFIG_CIFS_ACL */
3856
3857 /* Legacy Query Path Information call for lookup to old servers such
3858    as Win9x/WinME */
3859 int
3860 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3861                     const char *search_name, FILE_ALL_INFO *data,
3862                     const struct nls_table *nls_codepage, int remap)
3863 {
3864         QUERY_INFORMATION_REQ *pSMB;
3865         QUERY_INFORMATION_RSP *pSMBr;
3866         int rc = 0;
3867         int bytes_returned;
3868         int name_len;
3869
3870         cFYI(1, "In SMBQPath path %s", search_name);
3871 QInfRetry:
3872         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3873                       (void **) &pSMBr);
3874         if (rc)
3875                 return rc;
3876
3877         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3878                 name_len =
3879                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3880                                            search_name, PATH_MAX, nls_codepage,
3881                                            remap);
3882                 name_len++;     /* trailing null */
3883                 name_len *= 2;
3884         } else {
3885                 name_len = strnlen(search_name, PATH_MAX);
3886                 name_len++;     /* trailing null */
3887                 strncpy(pSMB->FileName, search_name, name_len);
3888         }
3889         pSMB->BufferFormat = 0x04;
3890         name_len++; /* account for buffer type byte */
3891         inc_rfc1001_len(pSMB, (__u16)name_len);
3892         pSMB->ByteCount = cpu_to_le16(name_len);
3893
3894         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3895                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3896         if (rc) {
3897                 cFYI(1, "Send error in QueryInfo = %d", rc);
3898         } else if (data) {
3899                 struct timespec ts;
3900                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3901
3902                 /* decode response */
3903                 /* BB FIXME - add time zone adjustment BB */
3904                 memset(data, 0, sizeof(FILE_ALL_INFO));
3905                 ts.tv_nsec = 0;
3906                 ts.tv_sec = time;
3907                 /* decode time fields */
3908                 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3909                 data->LastWriteTime = data->ChangeTime;
3910                 data->LastAccessTime = 0;
3911                 data->AllocationSize =
3912                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3913                 data->EndOfFile = data->AllocationSize;
3914                 data->Attributes =
3915                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3916         } else
3917                 rc = -EIO; /* bad buffer passed in */
3918
3919         cifs_buf_release(pSMB);
3920
3921         if (rc == -EAGAIN)
3922                 goto QInfRetry;
3923
3924         return rc;
3925 }
3926
3927 int
3928 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3929                  u16 netfid, FILE_ALL_INFO *pFindData)
3930 {
3931         struct smb_t2_qfi_req *pSMB = NULL;
3932         struct smb_t2_qfi_rsp *pSMBr = NULL;
3933         int rc = 0;
3934         int bytes_returned;
3935         __u16 params, byte_count;
3936
3937 QFileInfoRetry:
3938         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3939                       (void **) &pSMBr);
3940         if (rc)
3941                 return rc;
3942
3943         params = 2 /* level */ + 2 /* fid */;
3944         pSMB->t2.TotalDataCount = 0;
3945         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3946         /* BB find exact max data count below from sess structure BB */
3947         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3948         pSMB->t2.MaxSetupCount = 0;
3949         pSMB->t2.Reserved = 0;
3950         pSMB->t2.Flags = 0;
3951         pSMB->t2.Timeout = 0;
3952         pSMB->t2.Reserved2 = 0;
3953         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3954                                                Fid) - 4);
3955         pSMB->t2.DataCount = 0;
3956         pSMB->t2.DataOffset = 0;
3957         pSMB->t2.SetupCount = 1;
3958         pSMB->t2.Reserved3 = 0;
3959         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3960         byte_count = params + 1 /* pad */ ;
3961         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3962         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3963         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3964         pSMB->Pad = 0;
3965         pSMB->Fid = netfid;
3966         inc_rfc1001_len(pSMB, byte_count);
3967
3968         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3969                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3970         if (rc) {
3971                 cFYI(1, "Send error in QPathInfo = %d", rc);
3972         } else {                /* decode response */
3973                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3974
3975                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3976                         rc = -EIO;
3977                 else if (get_bcc(&pSMBr->hdr) < 40)
3978                         rc = -EIO;      /* bad smb */
3979                 else if (pFindData) {
3980                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3981                         memcpy((char *) pFindData,
3982                                (char *) &pSMBr->hdr.Protocol +
3983                                data_offset, sizeof(FILE_ALL_INFO));
3984                 } else
3985                     rc = -ENOMEM;
3986         }
3987         cifs_buf_release(pSMB);
3988         if (rc == -EAGAIN)
3989                 goto QFileInfoRetry;
3990
3991         return rc;
3992 }
3993
3994 int
3995 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3996                  const char *search_name, FILE_ALL_INFO *data,
3997                  int legacy /* old style infolevel */,
3998                  const struct nls_table *nls_codepage, int remap)
3999 {
4000         /* level 263 SMB_QUERY_FILE_ALL_INFO */
4001         TRANSACTION2_QPI_REQ *pSMB = NULL;
4002         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4003         int rc = 0;
4004         int bytes_returned;
4005         int name_len;
4006         __u16 params, byte_count;
4007
4008         /* cFYI(1, "In QPathInfo path %s", search_name); */
4009 QPathInfoRetry:
4010         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4011                       (void **) &pSMBr);
4012         if (rc)
4013                 return rc;
4014
4015         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4016                 name_len =
4017                     cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4018                                        PATH_MAX, nls_codepage, remap);
4019                 name_len++;     /* trailing null */
4020                 name_len *= 2;
4021         } else {        /* BB improve the check for buffer overruns BB */
4022                 name_len = strnlen(search_name, PATH_MAX);
4023                 name_len++;     /* trailing null */
4024                 strncpy(pSMB->FileName, search_name, name_len);
4025         }
4026
4027         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4028         pSMB->TotalDataCount = 0;
4029         pSMB->MaxParameterCount = cpu_to_le16(2);
4030         /* BB find exact max SMB PDU from sess structure BB */
4031         pSMB->MaxDataCount = cpu_to_le16(4000);
4032         pSMB->MaxSetupCount = 0;
4033         pSMB->Reserved = 0;
4034         pSMB->Flags = 0;
4035         pSMB->Timeout = 0;
4036         pSMB->Reserved2 = 0;
4037         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4038         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4039         pSMB->DataCount = 0;
4040         pSMB->DataOffset = 0;
4041         pSMB->SetupCount = 1;
4042         pSMB->Reserved3 = 0;
4043         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4044         byte_count = params + 1 /* pad */ ;
4045         pSMB->TotalParameterCount = cpu_to_le16(params);
4046         pSMB->ParameterCount = pSMB->TotalParameterCount;
4047         if (legacy)
4048                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4049         else
4050                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4051         pSMB->Reserved4 = 0;
4052         inc_rfc1001_len(pSMB, byte_count);
4053         pSMB->ByteCount = cpu_to_le16(byte_count);
4054
4055         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4056                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4057         if (rc) {
4058                 cFYI(1, "Send error in QPathInfo = %d", rc);
4059         } else {                /* decode response */
4060                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4061
4062                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4063                         rc = -EIO;
4064                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4065                         rc = -EIO;      /* bad smb */
4066                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4067                         rc = -EIO;  /* 24 or 26 expected but we do not read
4068                                         last field */
4069                 else if (data) {
4070                         int size;
4071                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4072
4073                         /*
4074                          * On legacy responses we do not read the last field,
4075                          * EAsize, fortunately since it varies by subdialect and
4076                          * also note it differs on Set vs Get, ie two bytes or 4
4077                          * bytes depending but we don't care here.
4078                          */
4079                         if (legacy)
4080                                 size = sizeof(FILE_INFO_STANDARD);
4081                         else
4082                                 size = sizeof(FILE_ALL_INFO);
4083                         memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4084                                data_offset, size);
4085                 } else
4086                     rc = -ENOMEM;
4087         }
4088         cifs_buf_release(pSMB);
4089         if (rc == -EAGAIN)
4090                 goto QPathInfoRetry;
4091
4092         return rc;
4093 }
4094
4095 int
4096 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4097                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4098 {
4099         struct smb_t2_qfi_req *pSMB = NULL;
4100         struct smb_t2_qfi_rsp *pSMBr = NULL;
4101         int rc = 0;
4102         int bytes_returned;
4103         __u16 params, byte_count;
4104
4105 UnixQFileInfoRetry:
4106         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4107                       (void **) &pSMBr);
4108         if (rc)
4109                 return rc;
4110
4111         params = 2 /* level */ + 2 /* fid */;
4112         pSMB->t2.TotalDataCount = 0;
4113         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4114         /* BB find exact max data count below from sess structure BB */
4115         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4116         pSMB->t2.MaxSetupCount = 0;
4117         pSMB->t2.Reserved = 0;
4118         pSMB->t2.Flags = 0;
4119         pSMB->t2.Timeout = 0;
4120         pSMB->t2.Reserved2 = 0;
4121         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4122                                                Fid) - 4);
4123         pSMB->t2.DataCount = 0;
4124         pSMB->t2.DataOffset = 0;
4125         pSMB->t2.SetupCount = 1;
4126         pSMB->t2.Reserved3 = 0;
4127         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4128         byte_count = params + 1 /* pad */ ;
4129         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4130         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4131         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4132         pSMB->Pad = 0;
4133         pSMB->Fid = netfid;
4134         inc_rfc1001_len(pSMB, byte_count);
4135
4136         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4137                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4138         if (rc) {
4139                 cFYI(1, "Send error in QPathInfo = %d", rc);
4140         } else {                /* decode response */
4141                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4142
4143                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4144                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4145                                    "Unix Extensions can be disabled on mount "
4146                                    "by specifying the nosfu mount option.");
4147                         rc = -EIO;      /* bad smb */
4148                 } else {
4149                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4150                         memcpy((char *) pFindData,
4151                                (char *) &pSMBr->hdr.Protocol +
4152                                data_offset,
4153                                sizeof(FILE_UNIX_BASIC_INFO));
4154                 }
4155         }
4156
4157         cifs_buf_release(pSMB);
4158         if (rc == -EAGAIN)
4159                 goto UnixQFileInfoRetry;
4160
4161         return rc;
4162 }
4163
4164 int
4165 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4166                      const unsigned char *searchName,
4167                      FILE_UNIX_BASIC_INFO *pFindData,
4168                      const struct nls_table *nls_codepage, int remap)
4169 {
4170 /* SMB_QUERY_FILE_UNIX_BASIC */
4171         TRANSACTION2_QPI_REQ *pSMB = NULL;
4172         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4173         int rc = 0;
4174         int bytes_returned = 0;
4175         int name_len;
4176         __u16 params, byte_count;
4177
4178         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4179 UnixQPathInfoRetry:
4180         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4181                       (void **) &pSMBr);
4182         if (rc)
4183                 return rc;
4184
4185         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4186                 name_len =
4187                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4188                                        PATH_MAX, nls_codepage, remap);
4189                 name_len++;     /* trailing null */
4190                 name_len *= 2;
4191         } else {        /* BB improve the check for buffer overruns BB */
4192                 name_len = strnlen(searchName, PATH_MAX);
4193                 name_len++;     /* trailing null */
4194                 strncpy(pSMB->FileName, searchName, name_len);
4195         }
4196
4197         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4198         pSMB->TotalDataCount = 0;
4199         pSMB->MaxParameterCount = cpu_to_le16(2);
4200         /* BB find exact max SMB PDU from sess structure BB */
4201         pSMB->MaxDataCount = cpu_to_le16(4000);
4202         pSMB->MaxSetupCount = 0;
4203         pSMB->Reserved = 0;
4204         pSMB->Flags = 0;
4205         pSMB->Timeout = 0;
4206         pSMB->Reserved2 = 0;
4207         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4208         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4209         pSMB->DataCount = 0;
4210         pSMB->DataOffset = 0;
4211         pSMB->SetupCount = 1;
4212         pSMB->Reserved3 = 0;
4213         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4214         byte_count = params + 1 /* pad */ ;
4215         pSMB->TotalParameterCount = cpu_to_le16(params);
4216         pSMB->ParameterCount = pSMB->TotalParameterCount;
4217         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4218         pSMB->Reserved4 = 0;
4219         inc_rfc1001_len(pSMB, byte_count);
4220         pSMB->ByteCount = cpu_to_le16(byte_count);
4221
4222         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4223                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4224         if (rc) {
4225                 cFYI(1, "Send error in QPathInfo = %d", rc);
4226         } else {                /* decode response */
4227                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4228
4229                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4230                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response. "
4231                                    "Unix Extensions can be disabled on mount "
4232                                    "by specifying the nosfu mount option.");
4233                         rc = -EIO;      /* bad smb */
4234                 } else {
4235                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4236                         memcpy((char *) pFindData,
4237                                (char *) &pSMBr->hdr.Protocol +
4238                                data_offset,
4239                                sizeof(FILE_UNIX_BASIC_INFO));
4240                 }
4241         }
4242         cifs_buf_release(pSMB);
4243         if (rc == -EAGAIN)
4244                 goto UnixQPathInfoRetry;
4245
4246         return rc;
4247 }
4248
4249 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4250 int
4251 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4252               const char *searchName,
4253               const struct nls_table *nls_codepage,
4254               __u16 *pnetfid, __u16 search_flags,
4255               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4256 {
4257 /* level 257 SMB_ */
4258         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4259         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4260         T2_FFIRST_RSP_PARMS *parms;
4261         int rc = 0;
4262         int bytes_returned = 0;
4263         int name_len;
4264         __u16 params, byte_count;
4265
4266         cFYI(1, "In FindFirst for %s", searchName);
4267
4268 findFirstRetry:
4269         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4270                       (void **) &pSMBr);
4271         if (rc)
4272                 return rc;
4273
4274         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4275                 name_len =
4276                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4277                                        PATH_MAX, nls_codepage, remap);
4278                 /* We can not add the asterik earlier in case
4279                 it got remapped to 0xF03A as if it were part of the
4280                 directory name instead of a wildcard */
4281                 name_len *= 2;
4282                 pSMB->FileName[name_len] = dirsep;
4283                 pSMB->FileName[name_len+1] = 0;
4284                 pSMB->FileName[name_len+2] = '*';
4285                 pSMB->FileName[name_len+3] = 0;
4286                 name_len += 4; /* now the trailing null */
4287                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4288                 pSMB->FileName[name_len+1] = 0;
4289                 name_len += 2;
4290         } else {        /* BB add check for overrun of SMB buf BB */
4291                 name_len = strnlen(searchName, PATH_MAX);
4292 /* BB fix here and in unicode clause above ie
4293                 if (name_len > buffersize-header)
4294                         free buffer exit; BB */
4295                 strncpy(pSMB->FileName, searchName, name_len);
4296                 pSMB->FileName[name_len] = dirsep;
4297                 pSMB->FileName[name_len+1] = '*';
4298                 pSMB->FileName[name_len+2] = 0;
4299                 name_len += 3;
4300         }
4301
4302         params = 12 + name_len /* includes null */ ;
4303         pSMB->TotalDataCount = 0;       /* no EAs */
4304         pSMB->MaxParameterCount = cpu_to_le16(10);
4305         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4306         pSMB->MaxSetupCount = 0;
4307         pSMB->Reserved = 0;
4308         pSMB->Flags = 0;
4309         pSMB->Timeout = 0;
4310         pSMB->Reserved2 = 0;
4311         byte_count = params + 1 /* pad */ ;
4312         pSMB->TotalParameterCount = cpu_to_le16(params);
4313         pSMB->ParameterCount = pSMB->TotalParameterCount;
4314         pSMB->ParameterOffset = cpu_to_le16(
4315               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4316                 - 4);
4317         pSMB->DataCount = 0;
4318         pSMB->DataOffset = 0;
4319         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4320         pSMB->Reserved3 = 0;
4321         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4322         pSMB->SearchAttributes =
4323             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4324                         ATTR_DIRECTORY);
4325         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4326         pSMB->SearchFlags = cpu_to_le16(search_flags);
4327         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4328
4329         /* BB what should we set StorageType to? Does it matter? BB */
4330         pSMB->SearchStorageType = 0;
4331         inc_rfc1001_len(pSMB, byte_count);
4332         pSMB->ByteCount = cpu_to_le16(byte_count);
4333
4334         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4335                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4336         cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4337
4338         if (rc) {/* BB add logic to retry regular search if Unix search
4339                         rejected unexpectedly by server */
4340                 /* BB Add code to handle unsupported level rc */
4341                 cFYI(1, "Error in FindFirst = %d", rc);
4342
4343                 cifs_buf_release(pSMB);
4344
4345                 /* BB eventually could optimize out free and realloc of buf */
4346                 /*    for this case */
4347                 if (rc == -EAGAIN)
4348                         goto findFirstRetry;
4349         } else { /* decode response */
4350                 /* BB remember to free buffer if error BB */
4351                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4352                 if (rc == 0) {
4353                         unsigned int lnoff;
4354
4355                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4356                                 psrch_inf->unicode = true;
4357                         else
4358                                 psrch_inf->unicode = false;
4359
4360                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4361                         psrch_inf->smallBuf = 0;
4362                         psrch_inf->srch_entries_start =
4363                                 (char *) &pSMBr->hdr.Protocol +
4364                                         le16_to_cpu(pSMBr->t2.DataOffset);
4365                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4366                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4367
4368                         if (parms->EndofSearch)
4369                                 psrch_inf->endOfSearch = true;
4370                         else
4371                                 psrch_inf->endOfSearch = false;
4372
4373                         psrch_inf->entries_in_buffer =
4374                                         le16_to_cpu(parms->SearchCount);
4375                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4376                                 psrch_inf->entries_in_buffer;
4377                         lnoff = le16_to_cpu(parms->LastNameOffset);
4378                         if (CIFSMaxBufSize < lnoff) {
4379                                 cERROR(1, "ignoring corrupt resume name");
4380                                 psrch_inf->last_entry = NULL;
4381                                 return rc;
4382                         }
4383
4384                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4385                                                         lnoff;
4386
4387                         *pnetfid = parms->SearchHandle;
4388                 } else {
4389                         cifs_buf_release(pSMB);
4390                 }
4391         }
4392
4393         return rc;
4394 }
4395
4396 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4397                  __u16 searchHandle, __u16 search_flags,
4398                  struct cifs_search_info *psrch_inf)
4399 {
4400         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4401         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4402         T2_FNEXT_RSP_PARMS *parms;
4403         char *response_data;
4404         int rc = 0;
4405         int bytes_returned;
4406         unsigned int name_len;
4407         __u16 params, byte_count;
4408
4409         cFYI(1, "In FindNext");
4410
4411         if (psrch_inf->endOfSearch)
4412                 return -ENOENT;
4413
4414         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4415                 (void **) &pSMBr);
4416         if (rc)
4417                 return rc;
4418
4419         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4420         byte_count = 0;
4421         pSMB->TotalDataCount = 0;       /* no EAs */
4422         pSMB->MaxParameterCount = cpu_to_le16(8);
4423         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4424         pSMB->MaxSetupCount = 0;
4425         pSMB->Reserved = 0;
4426         pSMB->Flags = 0;
4427         pSMB->Timeout = 0;
4428         pSMB->Reserved2 = 0;
4429         pSMB->ParameterOffset =  cpu_to_le16(
4430               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4431         pSMB->DataCount = 0;
4432         pSMB->DataOffset = 0;
4433         pSMB->SetupCount = 1;
4434         pSMB->Reserved3 = 0;
4435         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4436         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4437         pSMB->SearchCount =
4438                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4439         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4440         pSMB->ResumeKey = psrch_inf->resume_key;
4441         pSMB->SearchFlags = cpu_to_le16(search_flags);
4442
4443         name_len = psrch_inf->resume_name_len;
4444         params += name_len;
4445         if (name_len < PATH_MAX) {
4446                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4447                 byte_count += name_len;
4448                 /* 14 byte parm len above enough for 2 byte null terminator */
4449                 pSMB->ResumeFileName[name_len] = 0;
4450                 pSMB->ResumeFileName[name_len+1] = 0;
4451         } else {
4452                 rc = -EINVAL;
4453                 goto FNext2_err_exit;
4454         }
4455         byte_count = params + 1 /* pad */ ;
4456         pSMB->TotalParameterCount = cpu_to_le16(params);
4457         pSMB->ParameterCount = pSMB->TotalParameterCount;
4458         inc_rfc1001_len(pSMB, byte_count);
4459         pSMB->ByteCount = cpu_to_le16(byte_count);
4460
4461         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4462                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4463         cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4464         if (rc) {
4465                 if (rc == -EBADF) {
4466                         psrch_inf->endOfSearch = true;
4467                         cifs_buf_release(pSMB);
4468                         rc = 0; /* search probably was closed at end of search*/
4469                 } else
4470                         cFYI(1, "FindNext returned = %d", rc);
4471         } else {                /* decode response */
4472                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4473
4474                 if (rc == 0) {
4475                         unsigned int lnoff;
4476
4477                         /* BB fixme add lock for file (srch_info) struct here */
4478                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4479                                 psrch_inf->unicode = true;
4480                         else
4481                                 psrch_inf->unicode = false;
4482                         response_data = (char *) &pSMBr->hdr.Protocol +
4483                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4484                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4485                         response_data = (char *)&pSMBr->hdr.Protocol +
4486                                 le16_to_cpu(pSMBr->t2.DataOffset);
4487                         if (psrch_inf->smallBuf)
4488                                 cifs_small_buf_release(
4489                                         psrch_inf->ntwrk_buf_start);
4490                         else
4491                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4492                         psrch_inf->srch_entries_start = response_data;
4493                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4494                         psrch_inf->smallBuf = 0;
4495                         if (parms->EndofSearch)
4496                                 psrch_inf->endOfSearch = true;
4497                         else
4498                                 psrch_inf->endOfSearch = false;
4499                         psrch_inf->entries_in_buffer =
4500                                                 le16_to_cpu(parms->SearchCount);
4501                         psrch_inf->index_of_last_entry +=
4502                                 psrch_inf->entries_in_buffer;
4503                         lnoff = le16_to_cpu(parms->LastNameOffset);
4504                         if (CIFSMaxBufSize < lnoff) {
4505                                 cERROR(1, "ignoring corrupt resume name");
4506                                 psrch_inf->last_entry = NULL;
4507                                 return rc;
4508                         } else
4509                                 psrch_inf->last_entry =
4510                                         psrch_inf->srch_entries_start + lnoff;
4511
4512 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4513             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4514
4515                         /* BB fixme add unlock here */
4516                 }
4517
4518         }
4519
4520         /* BB On error, should we leave previous search buf (and count and
4521         last entry fields) intact or free the previous one? */
4522
4523         /* Note: On -EAGAIN error only caller can retry on handle based calls
4524         since file handle passed in no longer valid */
4525 FNext2_err_exit:
4526         if (rc != 0)
4527                 cifs_buf_release(pSMB);
4528         return rc;
4529 }
4530
4531 int
4532 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4533               const __u16 searchHandle)
4534 {
4535         int rc = 0;
4536         FINDCLOSE_REQ *pSMB = NULL;
4537
4538         cFYI(1, "In CIFSSMBFindClose");
4539         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4540
4541         /* no sense returning error if session restarted
4542                 as file handle has been closed */
4543         if (rc == -EAGAIN)
4544                 return 0;
4545         if (rc)
4546                 return rc;
4547
4548         pSMB->FileID = searchHandle;
4549         pSMB->ByteCount = 0;
4550         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4551         if (rc)
4552                 cERROR(1, "Send error in FindClose = %d", rc);
4553
4554         cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4555
4556         /* Since session is dead, search handle closed on server already */
4557         if (rc == -EAGAIN)
4558                 rc = 0;
4559
4560         return rc;
4561 }
4562
4563 int
4564 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4565                       const char *search_name, __u64 *inode_number,
4566                       const struct nls_table *nls_codepage, int remap)
4567 {
4568         int rc = 0;
4569         TRANSACTION2_QPI_REQ *pSMB = NULL;
4570         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4571         int name_len, bytes_returned;
4572         __u16 params, byte_count;
4573
4574         cFYI(1, "In GetSrvInodeNum for %s", search_name);
4575         if (tcon == NULL)
4576                 return -ENODEV;
4577
4578 GetInodeNumberRetry:
4579         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4580                       (void **) &pSMBr);
4581         if (rc)
4582                 return rc;
4583
4584         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4585                 name_len =
4586                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4587                                            search_name, PATH_MAX, nls_codepage,
4588                                            remap);
4589                 name_len++;     /* trailing null */
4590                 name_len *= 2;
4591         } else {        /* BB improve the check for buffer overruns BB */
4592                 name_len = strnlen(search_name, PATH_MAX);
4593                 name_len++;     /* trailing null */
4594                 strncpy(pSMB->FileName, search_name, name_len);
4595         }
4596
4597         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4598         pSMB->TotalDataCount = 0;
4599         pSMB->MaxParameterCount = cpu_to_le16(2);
4600         /* BB find exact max data count below from sess structure BB */
4601         pSMB->MaxDataCount = cpu_to_le16(4000);
4602         pSMB->MaxSetupCount = 0;
4603         pSMB->Reserved = 0;
4604         pSMB->Flags = 0;
4605         pSMB->Timeout = 0;
4606         pSMB->Reserved2 = 0;
4607         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4608                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4609         pSMB->DataCount = 0;
4610         pSMB->DataOffset = 0;
4611         pSMB->SetupCount = 1;
4612         pSMB->Reserved3 = 0;
4613         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4614         byte_count = params + 1 /* pad */ ;
4615         pSMB->TotalParameterCount = cpu_to_le16(params);
4616         pSMB->ParameterCount = pSMB->TotalParameterCount;
4617         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4618         pSMB->Reserved4 = 0;
4619         inc_rfc1001_len(pSMB, byte_count);
4620         pSMB->ByteCount = cpu_to_le16(byte_count);
4621
4622         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4623                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4624         if (rc) {
4625                 cFYI(1, "error %d in QueryInternalInfo", rc);
4626         } else {
4627                 /* decode response */
4628                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4629                 /* BB also check enough total bytes returned */
4630                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4631                         /* If rc should we check for EOPNOSUPP and
4632                         disable the srvino flag? or in caller? */
4633                         rc = -EIO;      /* bad smb */
4634                 else {
4635                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4636                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4637                         struct file_internal_info *pfinfo;
4638                         /* BB Do we need a cast or hash here ? */
4639                         if (count < 8) {
4640                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4641                                 rc = -EIO;
4642                                 goto GetInodeNumOut;
4643                         }
4644                         pfinfo = (struct file_internal_info *)
4645                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4646                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4647                 }
4648         }
4649 GetInodeNumOut:
4650         cifs_buf_release(pSMB);
4651         if (rc == -EAGAIN)
4652                 goto GetInodeNumberRetry;
4653         return rc;
4654 }
4655
4656 /* parses DFS refferal V3 structure
4657  * caller is responsible for freeing target_nodes
4658  * returns:
4659  *      on success - 0
4660  *      on failure - errno
4661  */
4662 static int
4663 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4664                 unsigned int *num_of_nodes,
4665                 struct dfs_info3_param **target_nodes,
4666                 const struct nls_table *nls_codepage, int remap,
4667                 const char *searchName)
4668 {
4669         int i, rc = 0;
4670         char *data_end;
4671         bool is_unicode;
4672         struct dfs_referral_level_3 *ref;
4673
4674         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4675                 is_unicode = true;
4676         else
4677                 is_unicode = false;
4678         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4679
4680         if (*num_of_nodes < 1) {
4681                 cERROR(1, "num_referrals: must be at least > 0,"
4682                         "but we get num_referrals = %d", *num_of_nodes);
4683                 rc = -EINVAL;
4684                 goto parse_DFS_referrals_exit;
4685         }
4686
4687         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4688         if (ref->VersionNumber != cpu_to_le16(3)) {
4689                 cERROR(1, "Referrals of V%d version are not supported,"
4690                         "should be V3", le16_to_cpu(ref->VersionNumber));
4691                 rc = -EINVAL;
4692                 goto parse_DFS_referrals_exit;
4693         }
4694
4695         /* get the upper boundary of the resp buffer */
4696         data_end = (char *)(&(pSMBr->PathConsumed)) +
4697                                 le16_to_cpu(pSMBr->t2.DataCount);
4698
4699         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...",
4700                         *num_of_nodes,
4701                         le32_to_cpu(pSMBr->DFSFlags));
4702
4703         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4704                         *num_of_nodes, GFP_KERNEL);
4705         if (*target_nodes == NULL) {
4706                 cERROR(1, "Failed to allocate buffer for target_nodes");
4707                 rc = -ENOMEM;
4708                 goto parse_DFS_referrals_exit;
4709         }
4710
4711         /* collect necessary data from referrals */
4712         for (i = 0; i < *num_of_nodes; i++) {
4713                 char *temp;
4714                 int max_len;
4715                 struct dfs_info3_param *node = (*target_nodes)+i;
4716
4717                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4718                 if (is_unicode) {
4719                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4720                                                 GFP_KERNEL);
4721                         if (tmp == NULL) {
4722                                 rc = -ENOMEM;
4723                                 goto parse_DFS_referrals_exit;
4724                         }
4725                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4726                                            PATH_MAX, nls_codepage, remap);
4727                         node->path_consumed = cifs_utf16_bytes(tmp,
4728                                         le16_to_cpu(pSMBr->PathConsumed),
4729                                         nls_codepage);
4730                         kfree(tmp);
4731                 } else
4732                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4733
4734                 node->server_type = le16_to_cpu(ref->ServerType);
4735                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4736
4737                 /* copy DfsPath */
4738                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4739                 max_len = data_end - temp;
4740                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4741                                                 is_unicode, nls_codepage);
4742                 if (!node->path_name) {
4743                         rc = -ENOMEM;
4744                         goto parse_DFS_referrals_exit;
4745                 }
4746
4747                 /* copy link target UNC */
4748                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4749                 max_len = data_end - temp;
4750                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4751                                                 is_unicode, nls_codepage);
4752                 if (!node->node_name) {
4753                         rc = -ENOMEM;
4754                         goto parse_DFS_referrals_exit;
4755                 }
4756
4757                 ref++;
4758         }
4759
4760 parse_DFS_referrals_exit:
4761         if (rc) {
4762                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4763                 *target_nodes = NULL;
4764                 *num_of_nodes = 0;
4765         }
4766         return rc;
4767 }
4768
4769 int
4770 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4771                 const char *search_name, struct dfs_info3_param **target_nodes,
4772                 unsigned int *num_of_nodes,
4773                 const struct nls_table *nls_codepage, int remap)
4774 {
4775 /* TRANS2_GET_DFS_REFERRAL */
4776         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4777         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4778         int rc = 0;
4779         int bytes_returned;
4780         int name_len;
4781         __u16 params, byte_count;
4782         *num_of_nodes = 0;
4783         *target_nodes = NULL;
4784
4785         cFYI(1, "In GetDFSRefer the path %s", search_name);
4786         if (ses == NULL)
4787                 return -ENODEV;
4788 getDFSRetry:
4789         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4790                       (void **) &pSMBr);
4791         if (rc)
4792                 return rc;
4793
4794         /* server pointer checked in called function,
4795         but should never be null here anyway */
4796         pSMB->hdr.Mid = get_next_mid(ses->server);
4797         pSMB->hdr.Tid = ses->ipc_tid;
4798         pSMB->hdr.Uid = ses->Suid;
4799         if (ses->capabilities & CAP_STATUS32)
4800                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4801         if (ses->capabilities & CAP_DFS)
4802                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4803
4804         if (ses->capabilities & CAP_UNICODE) {
4805                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4806                 name_len =
4807                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4808                                        search_name, PATH_MAX, nls_codepage,
4809                                        remap);
4810                 name_len++;     /* trailing null */
4811                 name_len *= 2;
4812         } else {        /* BB improve the check for buffer overruns BB */
4813                 name_len = strnlen(search_name, PATH_MAX);
4814                 name_len++;     /* trailing null */
4815                 strncpy(pSMB->RequestFileName, search_name, name_len);
4816         }
4817
4818         if (ses->server) {
4819                 if (ses->server->sec_mode &
4820                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4821                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4822         }
4823
4824         pSMB->hdr.Uid = ses->Suid;
4825
4826         params = 2 /* level */  + name_len /*includes null */ ;
4827         pSMB->TotalDataCount = 0;
4828         pSMB->DataCount = 0;
4829         pSMB->DataOffset = 0;
4830         pSMB->MaxParameterCount = 0;
4831         /* BB find exact max SMB PDU from sess structure BB */
4832         pSMB->MaxDataCount = cpu_to_le16(4000);
4833         pSMB->MaxSetupCount = 0;
4834         pSMB->Reserved = 0;
4835         pSMB->Flags = 0;
4836         pSMB->Timeout = 0;
4837         pSMB->Reserved2 = 0;
4838         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4839           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4840         pSMB->SetupCount = 1;
4841         pSMB->Reserved3 = 0;
4842         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4843         byte_count = params + 3 /* pad */ ;
4844         pSMB->ParameterCount = cpu_to_le16(params);
4845         pSMB->TotalParameterCount = pSMB->ParameterCount;
4846         pSMB->MaxReferralLevel = cpu_to_le16(3);
4847         inc_rfc1001_len(pSMB, byte_count);
4848         pSMB->ByteCount = cpu_to_le16(byte_count);
4849
4850         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4851                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4852         if (rc) {
4853                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4854                 goto GetDFSRefExit;
4855         }
4856         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4857
4858         /* BB Also check if enough total bytes returned? */
4859         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4860                 rc = -EIO;      /* bad smb */
4861                 goto GetDFSRefExit;
4862         }
4863
4864         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4865                                 get_bcc(&pSMBr->hdr),
4866                                 le16_to_cpu(pSMBr->t2.DataOffset));
4867
4868         /* parse returned result into more usable form */
4869         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4870                                  target_nodes, nls_codepage, remap,
4871                                  search_name);
4872
4873 GetDFSRefExit:
4874         cifs_buf_release(pSMB);
4875
4876         if (rc == -EAGAIN)
4877                 goto getDFSRetry;
4878
4879         return rc;
4880 }
4881
4882 /* Query File System Info such as free space to old servers such as Win 9x */
4883 int
4884 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4885               struct kstatfs *FSData)
4886 {
4887 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4888         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4889         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4890         FILE_SYSTEM_ALLOC_INFO *response_data;
4891         int rc = 0;
4892         int bytes_returned = 0;
4893         __u16 params, byte_count;
4894
4895         cFYI(1, "OldQFSInfo");
4896 oldQFSInfoRetry:
4897         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4898                 (void **) &pSMBr);
4899         if (rc)
4900                 return rc;
4901
4902         params = 2;     /* level */
4903         pSMB->TotalDataCount = 0;
4904         pSMB->MaxParameterCount = cpu_to_le16(2);
4905         pSMB->MaxDataCount = cpu_to_le16(1000);
4906         pSMB->MaxSetupCount = 0;
4907         pSMB->Reserved = 0;
4908         pSMB->Flags = 0;
4909         pSMB->Timeout = 0;
4910         pSMB->Reserved2 = 0;
4911         byte_count = params + 1 /* pad */ ;
4912         pSMB->TotalParameterCount = cpu_to_le16(params);
4913         pSMB->ParameterCount = pSMB->TotalParameterCount;
4914         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4915         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4916         pSMB->DataCount = 0;
4917         pSMB->DataOffset = 0;
4918         pSMB->SetupCount = 1;
4919         pSMB->Reserved3 = 0;
4920         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4921         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4922         inc_rfc1001_len(pSMB, byte_count);
4923         pSMB->ByteCount = cpu_to_le16(byte_count);
4924
4925         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4926                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4927         if (rc) {
4928                 cFYI(1, "Send error in QFSInfo = %d", rc);
4929         } else {                /* decode response */
4930                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4931
4932                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4933                         rc = -EIO;      /* bad smb */
4934                 else {
4935                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4936                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4937                                  get_bcc(&pSMBr->hdr), data_offset);
4938
4939                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4940                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4941                         FSData->f_bsize =
4942                                 le16_to_cpu(response_data->BytesPerSector) *
4943                                 le32_to_cpu(response_data->
4944                                         SectorsPerAllocationUnit);
4945                         FSData->f_blocks =
4946                                le32_to_cpu(response_data->TotalAllocationUnits);
4947                         FSData->f_bfree = FSData->f_bavail =
4948                                 le32_to_cpu(response_data->FreeAllocationUnits);
4949                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4950                              (unsigned long long)FSData->f_blocks,
4951                              (unsigned long long)FSData->f_bfree,
4952                              FSData->f_bsize);
4953                 }
4954         }
4955         cifs_buf_release(pSMB);
4956
4957         if (rc == -EAGAIN)
4958                 goto oldQFSInfoRetry;
4959
4960         return rc;
4961 }
4962
4963 int
4964 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4965                struct kstatfs *FSData)
4966 {
4967 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4968         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4969         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4970         FILE_SYSTEM_INFO *response_data;
4971         int rc = 0;
4972         int bytes_returned = 0;
4973         __u16 params, byte_count;
4974
4975         cFYI(1, "In QFSInfo");
4976 QFSInfoRetry:
4977         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4978                       (void **) &pSMBr);
4979         if (rc)
4980                 return rc;
4981
4982         params = 2;     /* level */
4983         pSMB->TotalDataCount = 0;
4984         pSMB->MaxParameterCount = cpu_to_le16(2);
4985         pSMB->MaxDataCount = cpu_to_le16(1000);
4986         pSMB->MaxSetupCount = 0;
4987         pSMB->Reserved = 0;
4988         pSMB->Flags = 0;
4989         pSMB->Timeout = 0;
4990         pSMB->Reserved2 = 0;
4991         byte_count = params + 1 /* pad */ ;
4992         pSMB->TotalParameterCount = cpu_to_le16(params);
4993         pSMB->ParameterCount = pSMB->TotalParameterCount;
4994         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4995                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4996         pSMB->DataCount = 0;
4997         pSMB->DataOffset = 0;
4998         pSMB->SetupCount = 1;
4999         pSMB->Reserved3 = 0;
5000         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5001         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5002         inc_rfc1001_len(pSMB, byte_count);
5003         pSMB->ByteCount = cpu_to_le16(byte_count);
5004
5005         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5006                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5007         if (rc) {
5008                 cFYI(1, "Send error in QFSInfo = %d", rc);
5009         } else {                /* decode response */
5010                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5011
5012                 if (rc || get_bcc(&pSMBr->hdr) < 24)
5013                         rc = -EIO;      /* bad smb */
5014                 else {
5015                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5016
5017                         response_data =
5018                             (FILE_SYSTEM_INFO
5019                              *) (((char *) &pSMBr->hdr.Protocol) +
5020                                  data_offset);
5021                         FSData->f_bsize =
5022                             le32_to_cpu(response_data->BytesPerSector) *
5023                             le32_to_cpu(response_data->
5024                                         SectorsPerAllocationUnit);
5025                         FSData->f_blocks =
5026                             le64_to_cpu(response_data->TotalAllocationUnits);
5027                         FSData->f_bfree = FSData->f_bavail =
5028                             le64_to_cpu(response_data->FreeAllocationUnits);
5029                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5030                              (unsigned long long)FSData->f_blocks,
5031                              (unsigned long long)FSData->f_bfree,
5032                              FSData->f_bsize);
5033                 }
5034         }
5035         cifs_buf_release(pSMB);
5036
5037         if (rc == -EAGAIN)
5038                 goto QFSInfoRetry;
5039
5040         return rc;
5041 }
5042
5043 int
5044 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5045 {
5046 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5047         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5048         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5049         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5050         int rc = 0;
5051         int bytes_returned = 0;
5052         __u16 params, byte_count;
5053
5054         cFYI(1, "In QFSAttributeInfo");
5055 QFSAttributeRetry:
5056         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5057                       (void **) &pSMBr);
5058         if (rc)
5059                 return rc;
5060
5061         params = 2;     /* level */
5062         pSMB->TotalDataCount = 0;
5063         pSMB->MaxParameterCount = cpu_to_le16(2);
5064         /* BB find exact max SMB PDU from sess structure BB */
5065         pSMB->MaxDataCount = cpu_to_le16(1000);
5066         pSMB->MaxSetupCount = 0;
5067         pSMB->Reserved = 0;
5068         pSMB->Flags = 0;
5069         pSMB->Timeout = 0;
5070         pSMB->Reserved2 = 0;
5071         byte_count = params + 1 /* pad */ ;
5072         pSMB->TotalParameterCount = cpu_to_le16(params);
5073         pSMB->ParameterCount = pSMB->TotalParameterCount;
5074         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5075                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5076         pSMB->DataCount = 0;
5077         pSMB->DataOffset = 0;
5078         pSMB->SetupCount = 1;
5079         pSMB->Reserved3 = 0;
5080         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5081         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5082         inc_rfc1001_len(pSMB, byte_count);
5083         pSMB->ByteCount = cpu_to_le16(byte_count);
5084
5085         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5086                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5087         if (rc) {
5088                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5089         } else {                /* decode response */
5090                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5091
5092                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5093                         /* BB also check if enough bytes returned */
5094                         rc = -EIO;      /* bad smb */
5095                 } else {
5096                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5097                         response_data =
5098                             (FILE_SYSTEM_ATTRIBUTE_INFO
5099                              *) (((char *) &pSMBr->hdr.Protocol) +
5100                                  data_offset);
5101                         memcpy(&tcon->fsAttrInfo, response_data,
5102                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5103                 }
5104         }
5105         cifs_buf_release(pSMB);
5106
5107         if (rc == -EAGAIN)
5108                 goto QFSAttributeRetry;
5109
5110         return rc;
5111 }
5112
5113 int
5114 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5115 {
5116 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5117         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5118         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5119         FILE_SYSTEM_DEVICE_INFO *response_data;
5120         int rc = 0;
5121         int bytes_returned = 0;
5122         __u16 params, byte_count;
5123
5124         cFYI(1, "In QFSDeviceInfo");
5125 QFSDeviceRetry:
5126         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5127                       (void **) &pSMBr);
5128         if (rc)
5129                 return rc;
5130
5131         params = 2;     /* level */
5132         pSMB->TotalDataCount = 0;
5133         pSMB->MaxParameterCount = cpu_to_le16(2);
5134         /* BB find exact max SMB PDU from sess structure BB */
5135         pSMB->MaxDataCount = cpu_to_le16(1000);
5136         pSMB->MaxSetupCount = 0;
5137         pSMB->Reserved = 0;
5138         pSMB->Flags = 0;
5139         pSMB->Timeout = 0;
5140         pSMB->Reserved2 = 0;
5141         byte_count = params + 1 /* pad */ ;
5142         pSMB->TotalParameterCount = cpu_to_le16(params);
5143         pSMB->ParameterCount = pSMB->TotalParameterCount;
5144         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5145                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5146
5147         pSMB->DataCount = 0;
5148         pSMB->DataOffset = 0;
5149         pSMB->SetupCount = 1;
5150         pSMB->Reserved3 = 0;
5151         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5152         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5153         inc_rfc1001_len(pSMB, byte_count);
5154         pSMB->ByteCount = cpu_to_le16(byte_count);
5155
5156         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5157                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5158         if (rc) {
5159                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5160         } else {                /* decode response */
5161                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5162
5163                 if (rc || get_bcc(&pSMBr->hdr) <
5164                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5165                         rc = -EIO;      /* bad smb */
5166                 else {
5167                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5168                         response_data =
5169                             (FILE_SYSTEM_DEVICE_INFO *)
5170                                 (((char *) &pSMBr->hdr.Protocol) +
5171                                  data_offset);
5172                         memcpy(&tcon->fsDevInfo, response_data,
5173                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5174                 }
5175         }
5176         cifs_buf_release(pSMB);
5177
5178         if (rc == -EAGAIN)
5179                 goto QFSDeviceRetry;
5180
5181         return rc;
5182 }
5183
5184 int
5185 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5186 {
5187 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5188         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5189         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5190         FILE_SYSTEM_UNIX_INFO *response_data;
5191         int rc = 0;
5192         int bytes_returned = 0;
5193         __u16 params, byte_count;
5194
5195         cFYI(1, "In QFSUnixInfo");
5196 QFSUnixRetry:
5197         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5198                                    (void **) &pSMB, (void **) &pSMBr);
5199         if (rc)
5200                 return rc;
5201
5202         params = 2;     /* level */
5203         pSMB->TotalDataCount = 0;
5204         pSMB->DataCount = 0;
5205         pSMB->DataOffset = 0;
5206         pSMB->MaxParameterCount = cpu_to_le16(2);
5207         /* BB find exact max SMB PDU from sess structure BB */
5208         pSMB->MaxDataCount = cpu_to_le16(100);
5209         pSMB->MaxSetupCount = 0;
5210         pSMB->Reserved = 0;
5211         pSMB->Flags = 0;
5212         pSMB->Timeout = 0;
5213         pSMB->Reserved2 = 0;
5214         byte_count = params + 1 /* pad */ ;
5215         pSMB->ParameterCount = cpu_to_le16(params);
5216         pSMB->TotalParameterCount = pSMB->ParameterCount;
5217         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5218                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5219         pSMB->SetupCount = 1;
5220         pSMB->Reserved3 = 0;
5221         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5222         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5223         inc_rfc1001_len(pSMB, byte_count);
5224         pSMB->ByteCount = cpu_to_le16(byte_count);
5225
5226         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5227                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5228         if (rc) {
5229                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5230         } else {                /* decode response */
5231                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5232
5233                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5234                         rc = -EIO;      /* bad smb */
5235                 } else {
5236                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5237                         response_data =
5238                             (FILE_SYSTEM_UNIX_INFO
5239                              *) (((char *) &pSMBr->hdr.Protocol) +
5240                                  data_offset);
5241                         memcpy(&tcon->fsUnixInfo, response_data,
5242                                sizeof(FILE_SYSTEM_UNIX_INFO));
5243                 }
5244         }
5245         cifs_buf_release(pSMB);
5246
5247         if (rc == -EAGAIN)
5248                 goto QFSUnixRetry;
5249
5250
5251         return rc;
5252 }
5253
5254 int
5255 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5256 {
5257 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5258         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5259         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5260         int rc = 0;
5261         int bytes_returned = 0;
5262         __u16 params, param_offset, offset, byte_count;
5263
5264         cFYI(1, "In SETFSUnixInfo");
5265 SETFSUnixRetry:
5266         /* BB switch to small buf init to save memory */
5267         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5268                                         (void **) &pSMB, (void **) &pSMBr);
5269         if (rc)
5270                 return rc;
5271
5272         params = 4;     /* 2 bytes zero followed by info level. */
5273         pSMB->MaxSetupCount = 0;
5274         pSMB->Reserved = 0;
5275         pSMB->Flags = 0;
5276         pSMB->Timeout = 0;
5277         pSMB->Reserved2 = 0;
5278         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5279                                 - 4;
5280         offset = param_offset + params;
5281
5282         pSMB->MaxParameterCount = cpu_to_le16(4);
5283         /* BB find exact max SMB PDU from sess structure BB */
5284         pSMB->MaxDataCount = cpu_to_le16(100);
5285         pSMB->SetupCount = 1;
5286         pSMB->Reserved3 = 0;
5287         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5288         byte_count = 1 /* pad */ + params + 12;
5289
5290         pSMB->DataCount = cpu_to_le16(12);
5291         pSMB->ParameterCount = cpu_to_le16(params);
5292         pSMB->TotalDataCount = pSMB->DataCount;
5293         pSMB->TotalParameterCount = pSMB->ParameterCount;
5294         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5295         pSMB->DataOffset = cpu_to_le16(offset);
5296
5297         /* Params. */
5298         pSMB->FileNum = 0;
5299         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5300
5301         /* Data. */
5302         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5303         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5304         pSMB->ClientUnixCap = cpu_to_le64(cap);
5305
5306         inc_rfc1001_len(pSMB, byte_count);
5307         pSMB->ByteCount = cpu_to_le16(byte_count);
5308
5309         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5310                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5311         if (rc) {
5312                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5313         } else {                /* decode response */
5314                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5315                 if (rc)
5316                         rc = -EIO;      /* bad smb */
5317         }
5318         cifs_buf_release(pSMB);
5319
5320         if (rc == -EAGAIN)
5321                 goto SETFSUnixRetry;
5322
5323         return rc;
5324 }
5325
5326
5327
5328 int
5329 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5330                    struct kstatfs *FSData)
5331 {
5332 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5333         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5334         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5335         FILE_SYSTEM_POSIX_INFO *response_data;
5336         int rc = 0;
5337         int bytes_returned = 0;
5338         __u16 params, byte_count;
5339
5340         cFYI(1, "In QFSPosixInfo");
5341 QFSPosixRetry:
5342         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5343                       (void **) &pSMBr);
5344         if (rc)
5345                 return rc;
5346
5347         params = 2;     /* level */
5348         pSMB->TotalDataCount = 0;
5349         pSMB->DataCount = 0;
5350         pSMB->DataOffset = 0;
5351         pSMB->MaxParameterCount = cpu_to_le16(2);
5352         /* BB find exact max SMB PDU from sess structure BB */
5353         pSMB->MaxDataCount = cpu_to_le16(100);
5354         pSMB->MaxSetupCount = 0;
5355         pSMB->Reserved = 0;
5356         pSMB->Flags = 0;
5357         pSMB->Timeout = 0;
5358         pSMB->Reserved2 = 0;
5359         byte_count = params + 1 /* pad */ ;
5360         pSMB->ParameterCount = cpu_to_le16(params);
5361         pSMB->TotalParameterCount = pSMB->ParameterCount;
5362         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5363                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5364         pSMB->SetupCount = 1;
5365         pSMB->Reserved3 = 0;
5366         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5367         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5368         inc_rfc1001_len(pSMB, byte_count);
5369         pSMB->ByteCount = cpu_to_le16(byte_count);
5370
5371         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5372                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5373         if (rc) {
5374                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5375         } else {                /* decode response */
5376                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5377
5378                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5379                         rc = -EIO;      /* bad smb */
5380                 } else {
5381                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5382                         response_data =
5383                             (FILE_SYSTEM_POSIX_INFO
5384                              *) (((char *) &pSMBr->hdr.Protocol) +
5385                                  data_offset);
5386                         FSData->f_bsize =
5387                                         le32_to_cpu(response_data->BlockSize);
5388                         FSData->f_blocks =
5389                                         le64_to_cpu(response_data->TotalBlocks);
5390                         FSData->f_bfree =
5391                             le64_to_cpu(response_data->BlocksAvail);
5392                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5393                                 FSData->f_bavail = FSData->f_bfree;
5394                         } else {
5395                                 FSData->f_bavail =
5396                                     le64_to_cpu(response_data->UserBlocksAvail);
5397                         }
5398                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5399                                 FSData->f_files =
5400                                      le64_to_cpu(response_data->TotalFileNodes);
5401                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5402                                 FSData->f_ffree =
5403                                       le64_to_cpu(response_data->FreeFileNodes);
5404                 }
5405         }
5406         cifs_buf_release(pSMB);
5407
5408         if (rc == -EAGAIN)
5409                 goto QFSPosixRetry;
5410
5411         return rc;
5412 }
5413
5414
5415 /* We can not use write of zero bytes trick to
5416    set file size due to need for large file support.  Also note that
5417    this SetPathInfo is preferred to SetFileInfo based method in next
5418    routine which is only needed to work around a sharing violation bug
5419    in Samba which this routine can run into */
5420
5421 int
5422 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5423               const char *fileName, __u64 size, bool SetAllocation,
5424               const struct nls_table *nls_codepage, int remap)
5425 {
5426         struct smb_com_transaction2_spi_req *pSMB = NULL;
5427         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5428         struct file_end_of_file_info *parm_data;
5429         int name_len;
5430         int rc = 0;
5431         int bytes_returned = 0;
5432         __u16 params, byte_count, data_count, param_offset, offset;
5433
5434         cFYI(1, "In SetEOF");
5435 SetEOFRetry:
5436         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5437                       (void **) &pSMBr);
5438         if (rc)
5439                 return rc;
5440
5441         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5442                 name_len =
5443                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5444                                        PATH_MAX, nls_codepage, remap);
5445                 name_len++;     /* trailing null */
5446                 name_len *= 2;
5447         } else {        /* BB improve the check for buffer overruns BB */
5448                 name_len = strnlen(fileName, PATH_MAX);
5449                 name_len++;     /* trailing null */
5450                 strncpy(pSMB->FileName, fileName, name_len);
5451         }
5452         params = 6 + name_len;
5453         data_count = sizeof(struct file_end_of_file_info);
5454         pSMB->MaxParameterCount = cpu_to_le16(2);
5455         pSMB->MaxDataCount = cpu_to_le16(4100);
5456         pSMB->MaxSetupCount = 0;
5457         pSMB->Reserved = 0;
5458         pSMB->Flags = 0;
5459         pSMB->Timeout = 0;
5460         pSMB->Reserved2 = 0;
5461         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5462                                 InformationLevel) - 4;
5463         offset = param_offset + params;
5464         if (SetAllocation) {
5465                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5466                         pSMB->InformationLevel =
5467                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5468                 else
5469                         pSMB->InformationLevel =
5470                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5471         } else /* Set File Size */  {
5472             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5473                     pSMB->InformationLevel =
5474                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5475             else
5476                     pSMB->InformationLevel =
5477                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5478         }
5479
5480         parm_data =
5481             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5482                                        offset);
5483         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5484         pSMB->DataOffset = cpu_to_le16(offset);
5485         pSMB->SetupCount = 1;
5486         pSMB->Reserved3 = 0;
5487         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5488         byte_count = 3 /* pad */  + params + data_count;
5489         pSMB->DataCount = cpu_to_le16(data_count);
5490         pSMB->TotalDataCount = pSMB->DataCount;
5491         pSMB->ParameterCount = cpu_to_le16(params);
5492         pSMB->TotalParameterCount = pSMB->ParameterCount;
5493         pSMB->Reserved4 = 0;
5494         inc_rfc1001_len(pSMB, byte_count);
5495         parm_data->FileSize = cpu_to_le64(size);
5496         pSMB->ByteCount = cpu_to_le16(byte_count);
5497         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5498                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5499         if (rc)
5500                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5501
5502         cifs_buf_release(pSMB);
5503
5504         if (rc == -EAGAIN)
5505                 goto SetEOFRetry;
5506
5507         return rc;
5508 }
5509
5510 int
5511 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size,
5512                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5513 {
5514         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5515         struct file_end_of_file_info *parm_data;
5516         int rc = 0;
5517         __u16 params, param_offset, offset, byte_count, count;
5518
5519         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5520                         (long long)size);
5521         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5522
5523         if (rc)
5524                 return rc;
5525
5526         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5527         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5528
5529         params = 6;
5530         pSMB->MaxSetupCount = 0;
5531         pSMB->Reserved = 0;
5532         pSMB->Flags = 0;
5533         pSMB->Timeout = 0;
5534         pSMB->Reserved2 = 0;
5535         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5536         offset = param_offset + params;
5537
5538         count = sizeof(struct file_end_of_file_info);
5539         pSMB->MaxParameterCount = cpu_to_le16(2);
5540         /* BB find exact max SMB PDU from sess structure BB */
5541         pSMB->MaxDataCount = cpu_to_le16(1000);
5542         pSMB->SetupCount = 1;
5543         pSMB->Reserved3 = 0;
5544         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5545         byte_count = 3 /* pad */  + params + count;
5546         pSMB->DataCount = cpu_to_le16(count);
5547         pSMB->ParameterCount = cpu_to_le16(params);
5548         pSMB->TotalDataCount = pSMB->DataCount;
5549         pSMB->TotalParameterCount = pSMB->ParameterCount;
5550         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5551         parm_data =
5552                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5553                                 + offset);
5554         pSMB->DataOffset = cpu_to_le16(offset);
5555         parm_data->FileSize = cpu_to_le64(size);
5556         pSMB->Fid = fid;
5557         if (SetAllocation) {
5558                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5559                         pSMB->InformationLevel =
5560                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5561                 else
5562                         pSMB->InformationLevel =
5563                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5564         } else /* Set File Size */  {
5565             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5566                     pSMB->InformationLevel =
5567                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5568             else
5569                     pSMB->InformationLevel =
5570                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5571         }
5572         pSMB->Reserved4 = 0;
5573         inc_rfc1001_len(pSMB, byte_count);
5574         pSMB->ByteCount = cpu_to_le16(byte_count);
5575         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5576         if (rc) {
5577                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5578         }
5579
5580         /* Note: On -EAGAIN error only caller can retry on handle based calls
5581                 since file handle passed in no longer valid */
5582
5583         return rc;
5584 }
5585
5586 /* Some legacy servers such as NT4 require that the file times be set on
5587    an open handle, rather than by pathname - this is awkward due to
5588    potential access conflicts on the open, but it is unavoidable for these
5589    old servers since the only other choice is to go from 100 nanosecond DCE
5590    time and resort to the original setpathinfo level which takes the ancient
5591    DOS time format with 2 second granularity */
5592 int
5593 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5594                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5595 {
5596         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5597         char *data_offset;
5598         int rc = 0;
5599         __u16 params, param_offset, offset, byte_count, count;
5600
5601         cFYI(1, "Set Times (via SetFileInfo)");
5602         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5603
5604         if (rc)
5605                 return rc;
5606
5607         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5608         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5609
5610         params = 6;
5611         pSMB->MaxSetupCount = 0;
5612         pSMB->Reserved = 0;
5613         pSMB->Flags = 0;
5614         pSMB->Timeout = 0;
5615         pSMB->Reserved2 = 0;
5616         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5617         offset = param_offset + params;
5618
5619         data_offset = (char *)pSMB +
5620                         offsetof(struct smb_hdr, Protocol) + offset;
5621
5622         count = sizeof(FILE_BASIC_INFO);
5623         pSMB->MaxParameterCount = cpu_to_le16(2);
5624         /* BB find max SMB PDU from sess */
5625         pSMB->MaxDataCount = cpu_to_le16(1000);
5626         pSMB->SetupCount = 1;
5627         pSMB->Reserved3 = 0;
5628         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5629         byte_count = 3 /* pad */  + params + count;
5630         pSMB->DataCount = cpu_to_le16(count);
5631         pSMB->ParameterCount = cpu_to_le16(params);
5632         pSMB->TotalDataCount = pSMB->DataCount;
5633         pSMB->TotalParameterCount = pSMB->ParameterCount;
5634         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5635         pSMB->DataOffset = cpu_to_le16(offset);
5636         pSMB->Fid = fid;
5637         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5638                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5639         else
5640                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5641         pSMB->Reserved4 = 0;
5642         inc_rfc1001_len(pSMB, byte_count);
5643         pSMB->ByteCount = cpu_to_le16(byte_count);
5644         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5645         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5646         if (rc)
5647                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5648
5649         /* Note: On -EAGAIN error only caller can retry on handle based calls
5650                 since file handle passed in no longer valid */
5651
5652         return rc;
5653 }
5654
5655 int
5656 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5657                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5658 {
5659         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5660         char *data_offset;
5661         int rc = 0;
5662         __u16 params, param_offset, offset, byte_count, count;
5663
5664         cFYI(1, "Set File Disposition (via SetFileInfo)");
5665         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5666
5667         if (rc)
5668                 return rc;
5669
5670         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5671         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5672
5673         params = 6;
5674         pSMB->MaxSetupCount = 0;
5675         pSMB->Reserved = 0;
5676         pSMB->Flags = 0;
5677         pSMB->Timeout = 0;
5678         pSMB->Reserved2 = 0;
5679         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5680         offset = param_offset + params;
5681
5682         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5683
5684         count = 1;
5685         pSMB->MaxParameterCount = cpu_to_le16(2);
5686     &