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