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