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