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